diff options
Diffstat (limited to 'lib/hipe')
-rw-r--r-- | lib/hipe/cerl/erl_bif_types.erl | 241 | ||||
-rw-r--r-- | lib/hipe/cerl/erl_types.erl | 34 | ||||
-rw-r--r-- | lib/hipe/doc/src/notes.xml | 112 | ||||
-rw-r--r-- | lib/hipe/doc/src/ref_man.xml | 2 | ||||
-rw-r--r-- | lib/hipe/icode/hipe_beam_to_icode.erl | 6 | ||||
-rw-r--r-- | lib/hipe/icode/hipe_icode_callgraph.erl | 2 | ||||
-rw-r--r-- | lib/hipe/icode/hipe_icode_exceptions.erl | 2 | ||||
-rw-r--r-- | lib/hipe/icode/hipe_icode_primops.erl | 13 | ||||
-rw-r--r-- | lib/hipe/icode/hipe_icode_range.erl | 364 | ||||
-rw-r--r-- | lib/hipe/main/hipe_main.erl | 6 | ||||
-rw-r--r-- | lib/hipe/ppc/hipe_ppc.erl | 172 | ||||
-rw-r--r-- | lib/hipe/ppc/hipe_ppc_assemble.erl | 76 | ||||
-rw-r--r-- | lib/hipe/ppc/hipe_ppc_frame.erl | 30 | ||||
-rw-r--r-- | lib/hipe/ppc/hipe_rtl_to_ppc.erl | 260 | ||||
-rw-r--r-- | lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl | 2 | ||||
-rw-r--r-- | lib/hipe/rtl/hipe_rtl.erl | 2 | ||||
-rw-r--r-- | lib/hipe/rtl/hipe_rtl_arch.erl | 57 | ||||
-rw-r--r-- | lib/hipe/rtl/hipe_rtl_arith.inc | 2 | ||||
-rw-r--r-- | lib/hipe/rtl/hipe_rtl_primops.erl | 2 | ||||
-rw-r--r-- | lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl | 2 | ||||
-rw-r--r-- | lib/hipe/rtl/hipe_tagscheme.erl | 4 | ||||
-rw-r--r-- | lib/hipe/vsn.mk | 2 |
22 files changed, 817 insertions, 576 deletions
diff --git a/lib/hipe/cerl/erl_bif_types.erl b/lib/hipe/cerl/erl_bif_types.erl index ed5bf03804..30b911c41b 100644 --- a/lib/hipe/cerl/erl_bif_types.erl +++ b/lib/hipe/cerl/erl_bif_types.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2010. All Rights Reserved. +%% Copyright Ericsson AB 2003-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -48,6 +48,7 @@ t_boolean/0, t_byte/0, t_char/0, + t_charlist/0, t_cons/0, t_cons/2, t_cons_hd/1, @@ -124,7 +125,8 @@ t_tuple/1, t_tuple_args/1, t_tuple_size/1, - t_tuple_subtypes/1 + t_tuple_subtypes/1, + t_unicode_string/0 ]). -ifdef(DO_ERL_BIF_TYPES_TEST). @@ -189,127 +191,19 @@ type(binary, referenced_byte_size, 1, Xs) -> strict(arg_types(binary, referenced_byte_size, 1), Xs, fun(_) -> t_non_neg_integer() end); %%-- code --------------------------------------------------------------------- -type(code, add_path, 1, Xs) -> - strict(arg_types(code, add_path, 1), Xs, - fun (_) -> - t_sup(t_atom('true'), - t_tuple([t_atom('error'), t_atom('bad_directory')])) - end); -type(code, add_patha, 1, Xs) -> - type(code, add_path, 1, Xs); -type(code, add_paths, 1, Xs) -> - strict(arg_types(code, add_paths, 1), Xs, fun(_) -> t_atom('ok') end); -type(code, add_pathsa, 1, Xs) -> - type(code, add_paths, 1, Xs); -type(code, add_pathsz, 1, Xs) -> - type(code, add_paths, 1, Xs); -type(code, add_pathz, 1, Xs) -> - type(code, add_path, 1, Xs); -type(code, all_loaded, 0, _) -> - t_list(t_tuple([t_atom(), t_code_loaded_fname_or_status()])); -type(code, compiler_dir, 0, _) -> - t_string(); -type(code, del_path, 1, Xs) -> - strict(arg_types(code, del_path, 1), Xs, - fun (_) -> - t_sup(t_boolean(), - t_tuple([t_atom('error'), t_atom('bad_name')])) - end); -type(code, delete, 1, Xs) -> - strict(arg_types(code, delete, 1), Xs, fun (_) -> t_boolean() end); -type(code, ensure_loaded, 1, Xs) -> - type(code, load_file, 1, Xs); type(code, get_chunk, 2, Xs) -> strict(arg_types(code, get_chunk, 2), Xs, fun (_) -> t_sup(t_binary(), t_atom('undefined')) end); -type(code, get_object_code, 1, Xs) -> - strict(arg_types(code, get_object_code, 1), Xs, - fun (_) -> - t_sup(t_tuple([t_atom(), t_binary(), t_string()]), - t_atom('error')) - end); -type(code, get_path, 0, _) -> - t_list(t_string()); -type(code, is_loaded, 1, Xs) -> - strict(arg_types(code, is_loaded, 1), Xs, - fun (_) -> - t_sup([t_tuple([t_atom('file'), t_code_loaded_fname_or_status()]), - t_atom('false')]) - end); -type(code, is_sticky, 1, Xs) -> - strict(arg_types(code, is_sticky, 1), Xs, fun (_) -> t_boolean() end); type(code, is_module_native, 1, Xs) -> strict(arg_types(code, is_module_native, 1), Xs, fun (_) -> t_sup(t_boolean(), t_atom('undefined')) end); -type(code, lib_dir, 0, _) -> - t_string(); -type(code, lib_dir, 1, Xs) -> - strict(arg_types(code, lib_dir, 1), Xs, - fun (_) -> - t_sup(t_string(), - t_tuple([t_atom('error'), t_atom('bad_name')])) - end); -type(code, load_abs, 1, Xs) -> - strict(arg_types(code, load_abs, 1), Xs, - fun ([_File]) -> t_code_load_return(t_atom()) end); % XXX: cheating -type(code, load_abs, 2, Xs) -> - strict(arg_types(code, load_abs, 2), Xs, - fun ([_File,Mod]) -> t_code_load_return(Mod) end); -type(code, load_binary, 3, Xs) -> - strict(arg_types(code, load_binary, 3), Xs, - fun ([Mod,_File,_Bin]) -> t_code_load_return(Mod) end); -type(code, load_file, 1, Xs) -> - strict(arg_types(code, load_file, 1), Xs, - fun ([Mod]) -> t_code_load_return(Mod) end); -type(code, load_native_partial, 2, Xs) -> - strict(arg_types(code, load_native_partial, 2), Xs, - fun ([Mod,_Bin]) -> t_code_load_return(Mod) end); -type(code, load_native_sticky, 3, Xs) -> - strict(arg_types(code, load_native_sticky, 3), Xs, - fun ([Mod,_Bin,_]) -> t_code_load_return(Mod) end); type(code, module_md5, 1, Xs) -> strict(arg_types(code, module_md5, 1), Xs, fun (_) -> t_sup(t_binary(), t_atom('undefined')) end); type(code, make_stub_module, 3, Xs) -> strict(arg_types(code, make_stub_module, 3), Xs, fun ([Mod,_,_]) -> Mod end); -type(code, priv_dir, 1, Xs) -> - strict(arg_types(code, priv_dir, 1), Xs, - fun (_) -> - t_sup(t_string(), t_tuple([t_atom('error'), t_atom('bad_name')])) - end); -type(code, purge, 1, Xs) -> - type(code, delete, 1, Xs); -type(code, rehash, 0, _) -> t_atom('ok'); -type(code, replace_path, 2, Xs) -> - strict(arg_types(code, replace_path, 2), Xs, - fun (_) -> - t_sup([t_atom('true'), - t_tuple([t_atom('error'), t_atom('bad_name')]), - t_tuple([t_atom('error'), t_atom('bad_directory')]), - t_tuple([t_atom('error'), - t_tuple([t_atom('badarg'), t_any()])])]) - end); -type(code, root_dir, 0, _) -> - t_string(); -type(code, set_path, 1, Xs) -> - strict(arg_types(code, set_path, 1), Xs, - fun (_) -> - t_sup([t_atom('true'), - t_tuple([t_atom('error'), t_atom('bad_path')]), - t_tuple([t_atom('error'), t_atom('bad_directory')])]) - end); -type(code, soft_purge, 1, Xs) -> - type(code, delete, 1, Xs); -type(code, stick_mod, 1, Xs) -> - strict(arg_types(code, stick_mod, 1), Xs, fun (_) -> t_atom('true') end); -type(code, unstick_mod, 1, Xs) -> - type(code, stick_mod, 1, Xs); -type(code, which, 1, Xs) -> - strict(arg_types(code, which, 1), Xs, - fun (_) -> - t_sup([t_code_loaded_fname_or_status(), - t_atom('non_existing')]) - end); +type(code, rehash, 0, _) -> + t_atom('ok'); %%-- erl_ddll ----------------------------------------------------------------- type(erl_ddll, demonitor, 1, Xs) -> type(erlang, demonitor, 1, Xs); @@ -1865,6 +1759,8 @@ type(erts_debug, flat_size, 1, Xs) -> strict(arg_types(erts_debug, flat_size, 1), Xs, fun (_) -> t_integer() end); type(erts_debug, get_internal_state, 1, _) -> t_any(); +type(erts_debug, instructions, 0, _) -> + t_list(t_list(t_byte())); type(erts_debug, lock_counters, 1, Xs) -> strict(arg_types(erts_debug, lock_counters, 1), Xs, fun ([Arg]) -> @@ -3330,80 +3226,16 @@ arg_types(binary, part, 3) -> arg_types(binary, referenced_byte_size, 1) -> [t_binary()]; %%------- code ---------------------------------------------------------------- -arg_types(code, add_path, 1) -> - [t_string()]; -arg_types(code, add_patha, 1) -> - arg_types(code, add_path, 1); -arg_types(code, add_paths, 1) -> - [t_list(t_string())]; -arg_types(code, add_pathsa, 1) -> - arg_types(code, add_paths, 1); -arg_types(code, add_pathsz, 1) -> - arg_types(code, add_paths, 1); -arg_types(code, add_pathz, 1) -> - arg_types(code, add_path, 1); -arg_types(code, all_loaded, 0) -> - []; -arg_types(code, compiler_dir, 0) -> - []; -arg_types(code, del_path, 1) -> - [t_sup(t_string(), t_atom())]; % OBS: differs from add_path/1 -arg_types(code, delete, 1) -> - [t_atom()]; -arg_types(code, ensure_loaded, 1) -> - arg_types(code, load_file, 1); arg_types(code, get_chunk, 2) -> [t_binary(), t_string()]; -arg_types(code, get_object_code, 1) -> - [t_atom()]; -arg_types(code, get_path, 0) -> - []; -arg_types(code, is_loaded, 1) -> - [t_atom()]; -arg_types(code, is_sticky, 1) -> - [t_atom()]; arg_types(code, is_module_native, 1) -> [t_atom()]; -arg_types(code, lib_dir, 0) -> - []; -arg_types(code, lib_dir, 1) -> - [t_atom()]; -arg_types(code, load_abs, 1) -> - [t_string()]; -arg_types(code, load_abs, 2) -> - [t_code_loaded_fname_or_status(), t_atom()]; -arg_types(code, load_binary, 3) -> - [t_atom(), t_code_loaded_fname_or_status(), t_binary()]; -arg_types(code, load_file, 1) -> - [t_atom()]; -arg_types(code, load_native_partial, 2) -> - [t_atom(), t_binary()]; -arg_types(code, load_native_sticky, 3) -> - [t_atom(), t_binary(), t_sup(t_binary(), t_atom('false'))]; arg_types(code, module_md5, 1) -> [t_binary()]; arg_types(code, make_stub_module, 3) -> [t_atom(), t_binary(), t_tuple([t_list(), t_list()])]; -arg_types(code, priv_dir, 1) -> - [t_atom()]; -arg_types(code, purge, 1) -> - arg_types(code, delete, 1); arg_types(code, rehash, 0) -> []; -arg_types(code, replace_path, 2) -> - [t_atom(), t_string()]; -arg_types(code, root_dir, 0) -> - []; -arg_types(code, set_path, 1) -> - [t_list(t_string())]; -arg_types(code, soft_purge, 1) -> - arg_types(code, delete, 1); -arg_types(code, stick_mod, 1) -> - [t_atom()]; -arg_types(code, unstick_mod, 1) -> - arg_types(code, stick_mod, 1); -arg_types(code, which, 1) -> - [t_atom()]; %%------- erl_ddll ------------------------------------------------------------ arg_types(erl_ddll, demonitor, 1) -> arg_types(erlang, demonitor, 1); @@ -3532,9 +3364,9 @@ arg_types(erlang, atom_to_binary, 2) -> arg_types(erlang, atom_to_list, 1) -> [t_atom()]; arg_types(erlang, binary_part, 2) -> - [t_binary(), t_tuple([t_integer(),t_integer()])]; + [t_binary(), t_tuple([t_non_neg_integer(), t_integer()])]; arg_types(erlang, binary_part, 3) -> - [t_binary(), t_integer(), t_integer()]; + [t_binary(), t_non_neg_integer(), t_integer()]; arg_types(erlang, binary_to_atom, 2) -> [t_binary(), t_encoding_a2b()]; arg_types(erlang, binary_to_existing_atom, 2) -> @@ -3797,9 +3629,10 @@ arg_types(erlang, nodes, 1) -> arg_types(erlang, now, 0) -> []; arg_types(erlang, open_port, 2) -> + ArgT = t_sup(t_unicode_string(), t_binary()), [t_sup(t_atom(), t_sup([t_tuple([t_atom('spawn'), t_string()]), t_tuple([t_atom('spawn_driver'), t_string()]), - t_tuple([t_atom('spawn_executable'), t_string()]), + t_tuple([t_atom('spawn_executable'), ArgT]), t_tuple([t_atom('fd'), t_integer(), t_integer()])])), t_list(t_sup(t_sup([t_atom('stream'), t_atom('exit_status'), @@ -3815,8 +3648,8 @@ arg_types(erlang, open_port, 2) -> t_tuple([t_atom('line'), t_integer()]), t_tuple([t_atom('cd'), t_string()]), t_tuple([t_atom('env'), t_list(t_tuple(2))]), % XXX: More - t_tuple([t_atom('args'), t_list(t_string())]), - t_tuple([t_atom('arg0'), t_string()])])))]; + t_tuple([t_atom('args'), t_list(ArgT)]), + t_tuple([t_atom('arg0'), ArgT])])))]; arg_types(erlang, phash, 2) -> [t_any(), t_pos_integer()]; arg_types(erlang, phash2, 1) -> @@ -4091,6 +3924,8 @@ arg_types(erts_debug, flat_size, 1) -> [t_any()]; arg_types(erts_debug, get_internal_state, 1) -> [t_any()]; +arg_types(erts_debug, instructions, 0) -> + []; arg_types(erts_debug, lock_counters, 1) -> [t_sup([t_atom(enabled), t_atom(info), @@ -4517,11 +4352,11 @@ arg_types(os, timestamp, 0) -> arg_types(re, compile, 1) -> [t_iodata()]; arg_types(re, compile, 2) -> - [t_iodata(), t_list(t_re_compile_option())]; + [t_sup(t_iodata(), t_charlist()), t_list(t_re_compile_option())]; arg_types(re, run, 2) -> - [t_iodata(), t_re_RE()]; + [t_sup(t_iodata(), t_charlist()), t_re_RE()]; arg_types(re, run, 3) -> - [t_iodata(), t_re_RE(), t_list(t_re_run_option())]; + [t_sup(t_iodata(), t_charlist()), t_re_RE(), t_list(t_re_run_option())]; %%------- string -------------------------------------------------------------- arg_types(string, chars, 2) -> [t_char(), t_non_neg_integer()]; @@ -4637,10 +4472,10 @@ t_endian() -> %% ===================================================================== t_binary_part() -> - t_tuple([t_non_neg_integer(),t_integer()]). + t_tuple([t_non_neg_integer(), t_integer()]). t_binary_canonical_part() -> - t_tuple([t_non_neg_integer(),t_non_neg_integer()]). + t_tuple([t_non_neg_integer(), t_non_neg_integer()]). t_binary_pattern() -> t_sup([t_binary(), @@ -4648,10 +4483,10 @@ t_binary_pattern() -> t_binary_compiled_pattern()]). t_binary_compiled_pattern() -> - t_tuple([t_atom('cp'),t_binary()]). + t_tuple([t_atom('cp'), t_binary()]). t_binary_options() -> - t_list(t_tuple([t_atom('scope'),t_binary_part()])). + t_list(t_tuple([t_atom('scope'), t_binary_part()])). %% ===================================================================== %% HTTP types documented in R12B-4 @@ -4801,7 +4636,8 @@ t_process_priority_level() -> t_sup([t_atom('max'), t_atom('high'), t_atom('normal'), t_atom('low')]). t_process_status() -> - t_sup([t_atom('runnable'), t_atom('running'), + t_sup([t_atom('exiting'), t_atom('garbage_collecting'), + t_atom('runnable'), t_atom('running'), t_atom('suspended'), t_atom('waiting')]). t_raise_errorclass() -> @@ -4940,10 +4776,11 @@ t_matchres() -> %% From the 'ets' documentation %%----------------------------- %% Option = Type | Access | named_table | {keypos,Pos} -%% | {heir,pid(),HeirData} | {heir,none} -%% | {write_concurrency,boolean()} +%% | {heir,pid(),HeirData} | {heir,none} | Tweaks %% Type = set | ordered_set | bag | duplicate_bag %% Access = public | protected | private +%% Tweaks = {write_concurrency,boolean()} +%% | {read_concurrency,boolean()} | compressed %% Pos = integer() %% HeirData = term() t_ets_new_options() -> @@ -4955,10 +4792,12 @@ t_ets_new_options() -> t_atom('protected'), t_atom('private'), t_atom('named_table'), + t_tuple([t_atom('keypos'), t_integer()]), t_tuple([t_atom('heir'), t_pid(), t_any()]), t_tuple([t_atom('heir'), t_atom('none')]), - t_tuple([t_atom('keypos'), t_integer()]), - t_tuple([t_atom('write_concurrency'), t_boolean()])])). + t_tuple([t_atom('write_concurrency'), t_boolean()]), + t_tuple([t_atom('read_concurrency'), t_boolean()]), + t_atom('compressed')])). t_ets_info_items() -> t_sup([t_atom('fixed'), @@ -4978,8 +4817,7 @@ t_ets_info_items() -> %% ===================================================================== t_prim_file_name() -> - t_sup([t_string(), - t_binary()]). + t_sup(t_unicode_string(), t_binary()). %% ===================================================================== %% These are used for the built-in functions of 'gen_tcp' @@ -5136,13 +4974,14 @@ t_re_MP() -> %% it's supposed to be an opaque data type t_tuple([t_atom('re_pattern'), t_integer(), t_integer(), t_binary()]). t_re_RE() -> - t_sup(t_re_MP(), t_iodata()). + t_sup([t_re_MP(), t_iodata(), t_charlist()]). t_re_compile_option() -> - t_sup([t_atoms(['anchored', 'caseless', 'dollar_endonly', 'dotall', - 'extended', 'firstline', 'multiline', 'no_auto_capture', - 'dupnames', 'ungreedy']), - t_tuple([t_atom('newline'), t_re_NLSpec()])]). + t_sup([t_atoms(['unicode', 'anchored', 'caseless', 'dollar_endonly', + 'dotall', 'extended', 'firstline', 'multiline', + 'no_auto_capture', 'dupnames', 'ungreedy']), + t_tuple([t_atom('newline'), t_re_NLSpec()]), + t_atoms(['bsr_anycrlf', 'bsr_unicode'])]). t_re_run_option() -> t_sup([t_atoms(['anchored', 'global', 'notbol', 'noteol', 'notempty']), @@ -5159,7 +4998,7 @@ t_re_Type() -> t_atoms(['index', 'list', 'binary']). t_re_NLSpec() -> - t_atoms(['cr', 'crlf', 'lf', 'anycrlf']). + t_atoms(['cr', 'crlf', 'lf', 'anycrlf', 'any']). t_re_ValueSpec() -> t_sup(t_atoms(['all', 'all_but_first', 'first', 'none']), t_re_ValueList()). diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index 1ed85af172..080d6936b2 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -62,6 +62,7 @@ t_boolean/0, t_byte/0, t_char/0, + t_charlist/0, t_collect_vars/1, t_cons/0, t_cons/2, @@ -195,6 +196,7 @@ t_tuple_size/1, t_tuple_sizes/1, t_tuple_subtypes/1, + t_unicode_string/0, t_unify/2, t_unify/3, t_unit/0, @@ -1455,6 +1457,26 @@ t_is_tuple(_) -> false. %% Non-primitive types, including some handy syntactic sugar types %% +-spec t_unicode_string() -> erl_type(). + +t_unicode_string() -> + t_list(t_unicode_char()). + +-spec t_charlist() -> erl_type(). + +t_charlist() -> + t_charlist(1). + +-spec t_charlist(non_neg_integer()) -> erl_type(). + +t_charlist(N) when N > 0 -> + t_maybe_improper_list(t_sup([t_unicode_char(), + t_unicode_binary(), + t_charlist(N-1)]), + t_sup(t_unicode_binary(), t_nil())); +t_charlist(0) -> + t_maybe_improper_list(t_any(), t_sup(t_unicode_binary(), t_nil())). + -spec t_constant() -> erl_type(). t_constant() -> @@ -1549,6 +1571,16 @@ t_parameterized_module() -> t_timeout() -> t_sup(t_non_neg_integer(), t_atom('infinity')). +-spec t_unicode_binary() -> erl_type(). + +t_unicode_binary() -> + t_binary(). % with characters encoded in UTF-8 coding standard + +-spec t_unicode_char() -> erl_type(). + +t_unicode_char() -> + t_integer(). % representing a valid unicode codepoint + %%----------------------------------------------------------------------------- %% Some built-in opaque types %% @@ -2825,7 +2857,7 @@ t_subtract(?list(Contents1, Termination1, Size1) = T, true -> case {Size1, Size2} of {?nonempty_qual, ?unknown_qual} -> ?none; - {?unknown_qual, ?nonempty_qual} -> Termination1; + {?unknown_qual, ?nonempty_qual} -> ?nil; {S, S} -> ?none end; false -> diff --git a/lib/hipe/doc/src/notes.xml b/lib/hipe/doc/src/notes.xml index c188db483d..434bfac64c 100644 --- a/lib/hipe/doc/src/notes.xml +++ b/lib/hipe/doc/src/notes.xml @@ -30,6 +30,118 @@ </header> <p>This document describes the changes made to HiPE.</p> +<section><title>Hipe 3.7.9</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix erroneous fail info of a hipe_bs_primop</p> + <p> + Own Id: OTP-9036</p> + </item> + <item> + <p> + The change fixes a bug in the translation of 'bs_add' + BEAM instruction to HiPE's Icode representation. When + these instructions appeared in a guard context the + previous translation was obviously buggy.</p> + <p> + Own Id: OTP-9044</p> + </item> + <item> + <p> + Sanitize the specs of the code module</p> + <p> + After the addition of unicode_binary() to the + file:filename() type, dialyzer started complaining about + erroneous or incomplete specs in some functions of the + 'code' module. The culprit was hard-coded information in + erl_bif_types for functions of this module, which were + not updated. Since these functions have proper specs + these days and code duplication (pun intended) is never a + good idea, their type information was removed from + erl_bif_types.</p> + <p> + While doing this, some erroneous comments were fixed in + the code module and also made sure that the code now runs + without dialyzer warnings even when the + -Wunmatched_returns option is used.</p> + <p> + Some cleanups were applied to erl_bif_types too.</p> + <p> + Own Id: OTP-9100</p> + </item> + <item> + <p> + Fix bug in the simplification of inexact comparisons</p> + <p> + On 31/1/2011 Paul Guyot reported a bug in the native code + compilation of inexact equality/inequality tests between + floats and integers. The relevant test was:</p> + <p> + f(X) -> Y = X / 2, Y == 0.</p> + <p> + and hipe erroneously evaluated the calls f(0) and f(0.0) + to 'false'.</p> + <p> + The culprit was in the simplification code of the Icode + range analysis which used an erroneous test (lists:any/1 + instead of lists:all/1).</p> + <p> + Own Id: OTP-9101</p> + </item> + <item> + <p> + Document exiting and garbage_collecting process statuses</p> + <p> + Own Id: OTP-9102</p> + </item> + <item> + <p> + Remove hipe constants pool</p> + <p> + Hipe constants used to be allocated within a single, + fixed-size pool for interaction with the garbage + collector. However, the garbage collector no longer + depends on constants being allocated within a single + pool, and the fixed size of the pool both meant + unnecessary allocations on most deployments and crashes + on deployments requiring more constants.</p> + <p> + The code was simplified to directly invoke erts_alloc. + Debugging and undocumented function + hipe_bifs:show_literals/0 was removed (it returned true + and output text to the console), and debugging and + undocumented function hipe_bifs:constants_size/0 was + rewritten with a global to count the size of allocated + constants.</p> + <p> + Own Id: OTP-9128</p> + </item> + </list> + </section> + +</section> + +<section><title>Hipe 3.7.8.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Several type specifications for standard libraries were + wrong in the R14B01 release. This is now corrected. The + corrections concern types in re,io,filename and the + module erlang itself.</p> + <p> + Own Id: OTP-9008</p> + </item> + </list> + </section> + +</section> + <section><title>Hipe 3.7.8</title> <section><title>Improvements and New Features</title> diff --git a/lib/hipe/doc/src/ref_man.xml b/lib/hipe/doc/src/ref_man.xml index 09d10147ee..bdafb61d08 100644 --- a/lib/hipe/doc/src/ref_man.xml +++ b/lib/hipe/doc/src/ref_man.xml @@ -4,7 +4,7 @@ <application xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2011</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/hipe/icode/hipe_beam_to_icode.erl b/lib/hipe/icode/hipe_beam_to_icode.erl index 920c94d85c..d7eb035551 100644 --- a/lib/hipe/icode/hipe_beam_to_icode.erl +++ b/lib/hipe/icode/hipe_beam_to_icode.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -918,7 +918,7 @@ trans_fun([{bs_add, {f,Lbl}, [Old,New,Unit], Res}|Instructions], Env) -> Succ = mk_label(new), [hipe_icode:mk_primop([Temp], '*', [NewVar, hipe_icode:mk_const(Unit)], - hipe_icode:label_name(Succ), Lbl), + hipe_icode:label_name(Succ), map_label(Lbl)), Succ] end end, @@ -930,7 +930,7 @@ trans_fun([{bs_add, {f,Lbl}, [Old,New,Unit], Res}|Instructions], Env) -> [FailLbl, hipe_icode:mk_fail([hipe_icode:mk_const(badarg)], error)]}; true -> - {Lbl, []} + {map_label(Lbl), []} end, IsPos = [hipe_icode:mk_if('>=', [Temp, hipe_icode:mk_const(0)], diff --git a/lib/hipe/icode/hipe_icode_callgraph.erl b/lib/hipe/icode/hipe_icode_callgraph.erl index 3dba8e1071..ae4b5785c4 100644 --- a/lib/hipe/icode/hipe_icode_callgraph.erl +++ b/lib/hipe/icode/hipe_icode_callgraph.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% Copyright Ericsson AB 2004-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in diff --git a/lib/hipe/icode/hipe_icode_exceptions.erl b/lib/hipe/icode/hipe_icode_exceptions.erl index 3c8f7b5712..00caffb24b 100644 --- a/lib/hipe/icode/hipe_icode_exceptions.erl +++ b/lib/hipe/icode/hipe_icode_exceptions.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% Copyright Ericsson AB 2004-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in diff --git a/lib/hipe/icode/hipe_icode_primops.erl b/lib/hipe/icode/hipe_icode_primops.erl index b0fe7eb708..a413531c07 100644 --- a/lib/hipe/icode/hipe_icode_primops.erl +++ b/lib/hipe/icode/hipe_icode_primops.erl @@ -2,19 +2,19 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. -%% +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -26,9 +26,6 @@ %% Notes : %% History : * 2001-06-13 Erik Johansson ([email protected]): %% Created. -%% -%% $Id$ -%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -module(hipe_icode_primops). @@ -197,7 +194,7 @@ fails(#element{}) -> true; %% fails(#gc_test{}) -> ??? fails({hipe_bs_primop, {bs_start_match, _}}) -> true; fails({hipe_bs_primop, {{bs_start_match, bitstr}, _}}) -> true; -fails({hipe_bs_primop, {{bs_start_match, ok_matchstate}, _}}) -> false; +fails({hipe_bs_primop, {{bs_start_match, ok_matchstate}, _}}) -> true; fails({hipe_bs_primop, {bs_get_binary, _, _}}) -> true; fails({hipe_bs_primop, {bs_get_binary_all, _, _}}) -> true; fails({hipe_bs_primop, {bs_get_binary_all_2, _, _}}) -> true; diff --git a/lib/hipe/icode/hipe_icode_range.erl b/lib/hipe/icode/hipe_icode_range.erl index c7e6a451af..c222e8a5d5 100644 --- a/lib/hipe/icode/hipe_icode_range.erl +++ b/lib/hipe/icode/hipe_icode_range.erl @@ -1,20 +1,20 @@ %% -*- erlang-indent-level: 2 -*- %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2007-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2007-2011. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %%%------------------------------------------------------------------- @@ -59,15 +59,17 @@ -record(range, {range :: range_rep(), other :: boolean()}). +-type range() :: #range{}. --record(ann, {range :: #range{}, +-record(ann, {range :: range(), type :: erl_types:erl_type(), count :: integer()}). +-type ann() :: #ann{}. --type range_anno() :: {range_anno, #ann{}, fun((#ann{}) -> string())}. --type args_fun() :: fun((mfa(),cfg()) -> [#range{}]). --type call_fun() :: fun((mfa(),[#range{}]) -> #range{}). --type final_fun() :: fun((mfa(),[#range{}]) -> ok). +-type range_anno() :: {'range_anno', ann(), fun((ann()) -> string())}. +-type args_fun() :: fun((mfa(), cfg()) -> [range()]). +-type call_fun() :: fun((mfa(), [range()]) -> range()). +-type final_fun() :: fun((mfa(), [range()]) -> 'ok'). -type data() :: {mfa(), args_fun(), call_fun(), final_fun()}. -type label() :: non_neg_integer(). -type info() :: gb_tree(). @@ -75,15 +77,15 @@ -type variable() :: #icode_variable{}. -type annotated_variable() :: #icode_variable{}. -type argument() :: #icode_const{} | variable(). --type three_range_fun() :: fun((#range{},#range{},#range{}) -> #range{}). +-type three_range_fun() :: fun((range(),range(),range()) -> range()). -type instr_split_info() :: {icode_instr(), [{label(),info()}]}. --type last_instr_return() :: {instr_split_info(), #range{}}. +-type last_instr_return() :: {instr_split_info(), range()}. -record(state, {info_map = gb_trees:empty() :: info(), counter = dict:new() :: dict(), cfg :: cfg(), liveness = gb_trees:empty() :: gb_tree(), - ret_type :: #range{}, + ret_type :: range(), lookup_fun :: call_fun(), result_action :: final_fun()}). @@ -108,8 +110,8 @@ cfg(Cfg, MFA, Options, Servers) -> -spec concurrent_cfg(cfg(), mfa(), pid()) -> cfg(). concurrent_cfg(Cfg, MFA, CompServer) -> - CompServer ! {ready, {MFA,self()}}, - {ArgsFun,CallFun,FinalFun} = do_analysis(Cfg, MFA), + CompServer ! {ready, {MFA, self()}}, + {ArgsFun, CallFun, FinalFun} = do_analysis(Cfg, MFA), Ans = do_rewrite(Cfg, MFA, ArgsFun, CallFun, FinalFun), CompServer ! {done_rewrite, MFA}, Ans. @@ -227,7 +229,7 @@ analyse_block(Label, Info, State, Rewrite) -> state__update_info(State2, InfoList, Rewrite). -spec analyse_BB([icode_instr()], info(), [icode_instr()], boolean(), call_fun()) -> - {[icode_instr()], [{label(),info()}], #range{}}. + {[icode_instr()], [{label(),info()}], range()}. analyse_BB([Last], Info, Code, Rewrite, LookupFun) -> {{NewI, LabelInfoList}, RetType} = @@ -266,9 +268,9 @@ handle_args(I, Info, WidenFun) -> %% io:format("Uses: ~p~nRanges: ~p~n", [Uses, PresentRanges]), JoinFun = fun(Var, Range) -> update_info(Var, Range, WidenFun) end, NewUses = lists:zipwith(JoinFun, Uses, PresentRanges), - hipe_icode:subst_uses(lists:zip(Uses, NewUses),I). + hipe_icode:subst_uses(lists:zip(Uses, NewUses), I). --spec join_info(#ann{}, #range{}, three_range_fun()) -> #ann{}. +-spec join_info(ann(), range(), three_range_fun()) -> ann(). join_info(Ann = #ann{range = R1, type = Type, count = ?WIDEN}, R2, Fun) -> Ann#ann{range = Fun(R1, R2, range_from_simple_type(Type))}; @@ -278,17 +280,17 @@ join_info(Ann = #ann{range = R1, type = Type, count = C}, R2, _Fun) when C < ?WI NewR -> Ann#ann{range = NewR, count = C+1} end. --spec join_three(#range{}, #range{}, #range{}) -> #range{}. +-spec join_three(range(), range(), range()) -> range(). join_three(R1, R2, R3) -> inf(sup(R1, R2), R3). --spec update_info(variable(), #range{}) -> annotated_variable(). +-spec update_info(variable(), range()) -> annotated_variable(). update_info(Var, Range) -> update_info(Var, Range, fun update_three/3). --spec update_info(variable(), #range{}, three_range_fun()) -> annotated_variable(). +-spec update_info(variable(), range(), three_range_fun()) -> annotated_variable(). update_info(Arg, R, Fun) -> case hipe_icode:is_annotated_variable(Arg) of @@ -299,7 +301,7 @@ update_info(Arg, R, Fun) -> Arg end. --spec update_info1(any(), #range{}, three_range_fun()) -> range_anno(). +-spec update_info1(any(), range(), three_range_fun()) -> range_anno(). update_info1({range_anno, Ann, _}, R2, Fun) -> make_range_anno(update_ann(Ann,R2,Fun)); @@ -314,71 +316,71 @@ update_ann(Ann = #ann{range = R1, type = Type, count = C}, R2, _Fun) -> NewR -> Ann#ann{range = NewR, count = C+1} end. --spec type_to_ann(erl_types:erl_type()) -> #ann{}. +-spec type_to_ann(erl_types:erl_type()) -> ann(). type_to_ann(Type) -> - #ann{range = range_from_simple_type(Type), type = t_limit(Type,1), count=1}. + #ann{range = range_from_simple_type(Type), type = t_limit(Type,1), count = 1}. --spec make_range_anno(#ann{}) -> range_anno(). +-spec make_range_anno(ann()) -> range_anno(). make_range_anno(Ann) -> {range_anno, Ann, fun pp_ann/1}. --spec update_three(#range{}, #range{}, #range{}) -> #range{}. +-spec update_three(range(), range(), range()) -> range(). update_three(_R1, R2, R3) -> inf(R2, R3). --spec safe_widen(#range{}, #range{}, #range{}) -> #range{}. +-spec safe_widen(range(), range(), range()) -> range(). safe_widen(#range{range=Old}, #range{range=New}, T = #range{range=Wide}) -> ResRange = - case {Old,New,Wide} of - {{Min,Max1},{Min,Max2},{_,Max}} -> - case inf_geq(OMax = next_up_limit(inf_max([Max1,Max2])),Max) of + case {Old, New, Wide} of + {{Min,Max1}, {Min,Max2}, {_,Max}} -> + case inf_geq(OMax = next_up_limit(inf_max([Max1, Max2])), Max) of true -> {Min,Max}; false -> {Min,OMax} end; - {{Min1,Max},{Min2,Max},{Min,_}} -> - case inf_geq(Min, OMin = next_down_limit(inf_min([Min1,Min2]))) of + {{Min1,Max}, {Min2,Max}, {Min,_}} -> + case inf_geq(Min, OMin = next_down_limit(inf_min([Min1, Min2]))) of true -> {Min,Max}; false -> {OMin,Max} end; - {{Min1,Max1},{Min2,Max2},{Min,Max}} -> + {{Min1,Max1}, {Min2,Max2}, {Min,Max}} -> RealMax = - case inf_geq(OMax = next_up_limit(inf_max([Max1,Max2])),Max) of + case inf_geq(OMax = next_up_limit(inf_max([Max1, Max2])), Max) of true -> Max; false -> OMax end, RealMin = - case inf_geq(Min, OMin = next_down_limit(inf_min([Min1,Min2]))) of + case inf_geq(Min, OMin = next_down_limit(inf_min([Min1, Min2]))) of true -> Min; false -> OMin end, - {RealMin,RealMax}; + {RealMin, RealMax}; _ -> Wide end, - T#range{range=ResRange}. + T#range{range = ResRange}. --spec widen(#range{}, #range{}, #range{}) -> #range{}. +-spec widen(range(), range(), range()) -> range(). widen(#range{range=Old}, #range{range=New}, T = #range{range=Wide}) -> ResRange = - case {Old,New,Wide} of - {{Min,_},{Min,Max2},{_,Max}} -> - case inf_geq(OMax = next_up_limit(Max2),Max) of + case {Old, New, Wide} of + {{Min,_}, {Min,Max2}, {_,Max}} -> + case inf_geq(OMax = next_up_limit(Max2), Max) of true -> {Min,Max}; false -> {Min,OMax} end; - {{_,Max},{Min2,Max},{Min,_}} -> + {{_,Max}, {Min2,Max}, {Min,_}} -> case inf_geq(Min, OMin = next_down_limit(Min2)) of true -> {Min,Max}; false -> {OMin,Max} end; - {_,{Min2,Max2},{Min,Max}} -> + {_, {Min2,Max2}, {Min,Max}} -> RealMax = - case inf_geq(OMax = next_up_limit(Max2),Max) of + case inf_geq(OMax = next_up_limit(Max2), Max) of true -> Max; false -> OMax end, @@ -387,11 +389,11 @@ widen(#range{range=Old}, #range{range=New}, T = #range{range=Wide}) -> true -> Min; false -> OMin end, - {RealMin,RealMax}; + {RealMin, RealMax}; _ -> Wide end, - T#range{range=ResRange}. + T#range{range = ResRange}. -spec analyse_call(#icode_call{}, call_fun()) -> #icode_call{}. @@ -421,7 +423,7 @@ analyse_move(Move) -> analyse_begin_handler(Handler) -> SubstList = - [{Dst,update_info(Dst,any_type())} || + [{Dst, update_info(Dst, any_type())} || Dst <- hipe_icode:begin_handler_dstlist(Handler)], hipe_icode:subst_defines(SubstList, Handler). @@ -494,14 +496,14 @@ analyse_switch_val(Switch, Info, Rewrite) -> end end. --spec update_infos(argument(), info(), [{#range{},label()}]) -> [{label(),info()}]. +-spec update_infos(argument(), info(), [{range(),label()}]) -> [{label(),info()}]. update_infos(Arg, Info, [{Range, Label}|Rest]) -> - [{Label,enter_define({Arg,Range},Info)} | update_infos(Arg,Info,Rest)]; + [{Label,enter_define({Arg,Range},Info)} | update_infos(Arg, Info, Rest)]; update_infos(_, _, []) -> []. --spec get_range_label_list([{argument(),label()}], #range{}, [{#range{},label()}]) -> - {#range{},[{#range{},label()}]}. +-spec get_range_label_list([{argument(),label()}], range(), [{range(),label()}]) -> + {range(),[{range(),label()}]}. get_range_label_list([{Val,Label}|Cases], SRange, Acc) -> VRange = get_range_from_arg(Val), @@ -516,7 +518,7 @@ get_range_label_list([], SRange, Acc) -> {PointTypes, _} = lists:unzip(Acc), {remove_point_types(SRange, PointTypes), Acc}. --spec update_switch(#icode_switch_val{}, [{#range{},label()}], boolean()) -> +-spec update_switch(#icode_switch_val{}, [{range(),label()}], boolean()) -> #icode_switch_val{}. update_switch(Switch, LabelRangeList, KeepFail) -> @@ -524,14 +526,14 @@ update_switch(Switch, LabelRangeList, KeepFail) -> case label_range_list_to_cases(LabelRangeList, []) of no_update -> Switch; - Cases -> + Cases -> hipe_icode:switch_val_cases_update(Switch, Cases) end, if KeepFail -> S2; true -> S2 end. --spec label_range_list_to_cases([{#range{},label()}], [{#icode_const{},label()}]) -> +-spec label_range_list_to_cases([{range(),label()}], [{#icode_const{},label()}]) -> 'no_update' | [{#icode_const{},label()}]. label_range_list_to_cases([{#range{range={C,C},other=false},Label}|Rest], @@ -586,9 +588,9 @@ analyse_last_call(Call, Info, LookupFun) -> NewInfo = enter_vals(NewI, Info), case hipe_icode:call_fail_label(Call) of [] -> - {NewI, [{Continuation,NewInfo}]}; + {NewI, [{Continuation, NewInfo}]}; Fail -> - {NewI, [{Continuation,NewInfo}, {Fail,Info}]} + {NewI, [{Continuation, NewInfo}, {Fail, Info}]} end. -spec analyse_if(#icode_if{}, info(), boolean()) -> @@ -596,16 +598,16 @@ analyse_last_call(Call, Info, LookupFun) -> analyse_if(If, Info, Rewrite) -> case hipe_icode:if_args(If) of - Args = [_,_] -> + [_, _] = Args -> analyse_sane_if(If, Info, Args, get_range_from_args(Args), Rewrite); _ -> TrueLabel = hipe_icode:if_true_label(If), FalseLabel = hipe_icode:if_false_label(If), - {If, [{TrueLabel,Info},{FalseLabel,Info}]} + {If, [{TrueLabel, Info}, {FalseLabel, Info}]} end. -spec analyse_sane_if(#icode_if{}, info(), [argument(),...], - [#range{},...], boolean()) -> + [range(),...], boolean()) -> {#icode_goto{} | #icode_if{}, [{label(), info()}]}. analyse_sane_if(If, Info, [Arg1, Arg2], [Range1, Range2], Rewrite) -> @@ -613,59 +615,61 @@ analyse_sane_if(If, Info, [Arg1, Arg2], [Range1, Range2], Rewrite) -> '>' -> {TrueRange2, TrueRange1, FalseRange2, FalseRange1} = range_inequality_propagation(Range2, Range1); - '==' -> - {TempTrueRange1, TempTrueRange2, FalseRange1, FalseRange2}= - range_equality_propagation(Range1, Range2), - TrueRange1 = set_other(TempTrueRange1,other(Range1)), - TrueRange2 = set_other(TempTrueRange2,other(Range2)); '<' -> - {TrueRange1, TrueRange2, FalseRange1, FalseRange2} = + {TrueRange1, TrueRange2, FalseRange1, FalseRange2} = range_inequality_propagation(Range1, Range2); '>=' -> {FalseRange1, FalseRange2, TrueRange1, TrueRange2} = range_inequality_propagation(Range1, Range2); '=<' -> - {FalseRange2, FalseRange1, TrueRange2, TrueRange1} = + {FalseRange2, FalseRange1, TrueRange2, TrueRange1} = range_inequality_propagation(Range2, Range1); '=:=' -> - {TrueRange1, TrueRange2, FalseRange1, FalseRange2}= + {TrueRange1, TrueRange2, FalseRange1, FalseRange2} = range_equality_propagation(Range1, Range2); '=/=' -> {FalseRange1, FalseRange2, TrueRange1, TrueRange2} = range_equality_propagation(Range1, Range2); + '==' -> + {TempTrueRange1, TempTrueRange2, FalseRange1, FalseRange2} = + range_equality_propagation(Range1, Range2), + TrueRange1 = set_other(TempTrueRange1, other(Range1)), + TrueRange2 = set_other(TempTrueRange2, other(Range2)); '/=' -> - {TempFalseRange1, TempFalseRange2, TrueRange1, TrueRange2}= + {TempFalseRange1, TempFalseRange2, TrueRange1, TrueRange2} = range_equality_propagation(Range1, Range2), - FalseRange1 = set_other(TempFalseRange1,other(Range1)), - FalseRange2 = set_other(TempFalseRange2,other(Range2)) + FalseRange1 = set_other(TempFalseRange1, other(Range1)), + FalseRange2 = set_other(TempFalseRange2, other(Range2)) end, - TrueLabel = hipe_icode:if_true_label(If), - FalseLabel = hipe_icode:if_false_label(If), - TrueInfo = - enter_defines([{Arg1,TrueRange1}, {Arg2,TrueRange2}],Info), - FalseInfo = - enter_defines([{Arg1,FalseRange1}, {Arg2,FalseRange2}],Info), - True = - case lists:any(fun range__is_none/1,[TrueRange1,TrueRange2]) of + %% io:format("TR1 = ~w\nTR2 = ~w\n", [TrueRange1, TrueRange2]), + True = + case lists:all(fun range__is_none/1, [TrueRange1, TrueRange2]) of true -> []; - false -> [{TrueLabel,TrueInfo}] + false -> + TrueLabel = hipe_icode:if_true_label(If), + TrueArgRanges = [{Arg1, TrueRange1}, {Arg2, TrueRange2}], + TrueInfo = enter_defines(TrueArgRanges, Info), + [{TrueLabel, TrueInfo}] end, - False = - case lists:any(fun range__is_none/1, [FalseRange1,FalseRange2]) of + %% io:format("FR1 = ~w\nFR2 = ~w\n", [FalseRange1, FalseRange2]), + False = + case lists:all(fun range__is_none/1, [FalseRange1, FalseRange2]) of true -> []; - false -> [{FalseLabel,FalseInfo}] + false -> + FalseLabel = hipe_icode:if_false_label(If), + FalseArgRanges = [{Arg1, FalseRange1}, {Arg2, FalseRange2}], + FalseInfo = enter_defines(FalseArgRanges, Info), + [{FalseLabel, FalseInfo}] end, - UpdateInfo = True++False, + UpdateInfo = True ++ False, NewIF = if Rewrite -> - %%io:format("~w~n~w~n", [{Arg1,FalseRange1},{Arg2,FalseRange2}]), - %%io:format("Any none: ~w~n", [lists:any(fun range__is_none/1,[FalseRange1,FalseRange2])]), case UpdateInfo of - [] -> %%This is weird + [] -> %% This is weird If; - [{Label,_Info}] -> + [{Label, _Info}] -> hipe_icode:mk_goto(Label); - [_,_] -> + [_, _] -> If end; true -> @@ -686,13 +690,13 @@ normalize_name(Name) -> Name -> Name end. --spec range_equality_propagation(#range{}, #range{}) -> - {#range{}, #range{}, #range{}, #range{}}. +-spec range_equality_propagation(range(), range()) -> + {range(), range(), range(), range()}. range_equality_propagation(Range_1, Range_2) -> True_range = inf(Range_1, Range_2), case {range(Range_1), range(Range_2)} of - {{N,N},{ N,N}} -> + {{N,N}, {N,N}} -> False_range_1 = none_range(), False_range_2 = none_range(); {{N1,N1}, {N2,N2}} -> @@ -710,8 +714,8 @@ range_equality_propagation(Range_1, Range_2) -> end, {True_range, True_range, False_range_1, False_range_2}. --spec range_inequality_propagation(#range{}, #range{}) -> - {#range{}, #range{}, #range{}, #range{}}. +-spec range_inequality_propagation(range(), range()) -> + {range(), range(), range(), range()}. %% Range1 < Range2 range_inequality_propagation(Range1, Range2) -> @@ -781,26 +785,24 @@ analyse_type(Type, Info, Rewrite) -> TrueRange = inf(any_range(), OldVarRange), FalseRange = inf(none_range(), OldVarRange); _ -> - TrueRange = inf(none_range(),OldVarRange), + TrueRange = inf(none_range(), OldVarRange), FalseRange = OldVarRange end, TrueLabel = hipe_icode:type_true_label(Type), FalseLabel = hipe_icode:type_false_label(Type), - TrueInfo = - enter_define({Arg,TrueRange},Info), - FalseInfo = - enter_define({Arg,FalseRange},Info), - True = + TrueInfo = enter_define({Arg, TrueRange}, Info), + FalseInfo = enter_define({Arg, FalseRange}, Info), + True = case range__is_none(TrueRange) of true -> []; - false -> [{TrueLabel,TrueInfo}] + false -> [{TrueLabel, TrueInfo}] end, - False = + False = case range__is_none(FalseRange) of true -> []; - false -> [{FalseLabel,FalseInfo}] + false -> [{FalseLabel, FalseInfo}] end, - UpdateInfo = True++False, + UpdateInfo = True ++ False, NewType = if Rewrite -> case UpdateInfo of @@ -808,15 +810,15 @@ analyse_type(Type, Info, Rewrite) -> Type; [{Label,_Info}] -> hipe_icode:mk_goto(Label); - [_,_] -> + [_, _] -> Type end; true -> Type end, - {NewType,True ++ False}. + {NewType, True ++ False}. --spec compare_with_integer(integer(), #range{}) -> {#range{}, #range{}}. +-spec compare_with_integer(integer(), range()) -> {range(), range()}. compare_with_integer(N, OldVarRange) -> TestRange = range_init({N, N}, false), @@ -843,13 +845,13 @@ compare_with_integer(N, OldVarRange) -> %%== Ranges ================================================================== --spec pp_ann(#ann{} | erl_types:erl_type()) -> string(). +-spec pp_ann(ann() | erl_types:erl_type()) -> string(). -pp_ann(#ann{range=#range{range=R, other=false}}) -> +pp_ann(#ann{range = #range{range = R, other = false}}) -> pp_range(R); -pp_ann(#ann{range=#range{range=empty, other=true}, type=Type}) -> +pp_ann(#ann{range = #range{range = empty, other = true}, type = Type}) -> t_to_string(Type); -pp_ann(#ann{range=#range{range=R, other=true}, type=Type}) -> +pp_ann(#ann{range = #range{range = R, other = true}, type = Type}) -> pp_range(R) ++ " | " ++ t_to_string(Type); pp_ann(Type) -> t_to_string(Type). @@ -867,12 +869,12 @@ val_to_string(pos_inf) -> "inf"; val_to_string(neg_inf) -> "-inf"; val_to_string(X) when is_integer(X) -> integer_to_list(X). --spec range_from_type(erl_types:erl_type()) -> [#range{}]. +-spec range_from_type(erl_types:erl_type()) -> [range()]. range_from_type(Type) -> [range_from_simple_type(T) || T <- t_to_tlist(Type)]. --spec range_from_simple_type(erl_types:erl_type()) -> #range{}. +-spec range_from_simple_type(erl_types:erl_type()) -> range(). range_from_simple_type(Type) -> None = t_none(), @@ -887,7 +889,7 @@ range_from_simple_type(Type) -> #range{range = Range, other = true} end. --spec range_init(range_rep(), boolean()) -> #range{}. +-spec range_init(range_rep(), boolean()) -> range(). range_init({Min, Max} = Range, Other) -> case inf_geq(Max, Min) of @@ -899,39 +901,39 @@ range_init({Min, Max} = Range, Other) -> range_init(empty, Other) -> #range{range = empty, other = Other}. --spec range(#range{}) -> range_rep(). +-spec range(range()) -> range_rep(). range(#range{range = R}) -> R. --spec other(#range{}) -> boolean(). +-spec other(range()) -> boolean(). other(#range{other = O}) -> O. --spec set_other(#range{}, boolean()) -> #range{}. +-spec set_other(range(), boolean()) -> range(). set_other(R, O) -> R#range{other = O}. --spec range__min(#range{}) -> 'empty' | 'neg_inf' | integer(). +-spec range__min(range()) -> 'empty' | 'neg_inf' | integer(). -range__min(#range{range=empty}) -> empty; -range__min(#range{range={Min,_}}) -> Min. +range__min(#range{range = empty}) -> empty; +range__min(#range{range = {Min,_}}) -> Min. --spec range__max(#range{}) -> 'empty' | 'pos_inf' | integer(). +-spec range__max(range()) -> 'empty' | 'pos_inf' | integer(). -range__max(#range{range=empty}) -> empty; -range__max(#range{range={_,Max}}) -> Max. +range__max(#range{range = empty}) -> empty; +range__max(#range{range = {_,Max}}) -> Max. --spec range__is_none(#range{}) -> boolean(). +-spec range__is_none(range()) -> boolean(). -range__is_none(#range{range=empty, other=false}) -> true; +range__is_none(#range{range = empty, other = false}) -> true; range__is_none(#range{}) -> false. --spec range__is_empty(#range{}) -> boolean(). +-spec range__is_empty(range()) -> boolean(). -range__is_empty(#range{range=empty}) -> true; -range__is_empty(#range{range={_,_}}) -> false. +range__is_empty(#range{range = empty}) -> true; +range__is_empty(#range{range = {_,_}}) -> false. --spec remove_point_types(#range{}, [#range{}]) -> #range{}. +-spec remove_point_types(range(), [range()]) -> range(). remove_point_types(Range, Ranges) -> Sorted = lists:sort(Ranges), @@ -939,35 +941,35 @@ remove_point_types(Range, Ranges) -> Range1 = lists:foldl(FoldFun, Range, Sorted), lists:foldl(FoldFun, Range1, lists:reverse(Sorted)). --spec range__remove_constant(#range{}, #range{}) -> #range{}. +-spec range__remove_constant(range(), range()) -> range(). -range__remove_constant(R = #range{range={C,C}}, #range{range={C,C}}) -> - R#range{range=empty}; -range__remove_constant(R = #range{range={C,H}}, #range{range={C,C}}) -> - R#range{range={C+1,H}}; -range__remove_constant(R = #range{range={L,C}}, #range{range={C,C}}) -> - R#range{range={L,C-1}}; -range__remove_constant(R = #range{}, #range{range={C,C}}) -> +range__remove_constant(#range{range = {C, C}} = R, #range{range = {C, C}}) -> + R#range{range = empty}; +range__remove_constant(#range{range = {C, H}} = R, #range{range = {C, C}}) -> + R#range{range = {C+1, H}}; +range__remove_constant(#range{range = {L, C}} = R, #range{range = {C, C}}) -> + R#range{range = {L, C-1}}; +range__remove_constant(#range{} = R, #range{range = {C,C}}) -> R; -range__remove_constant(R = #range{}, _) -> +range__remove_constant(#range{} = R, _) -> R. --spec any_type() -> #range{}. +-spec any_type() -> range(). any_type() -> - #range{range=any_r(), other=true}. + #range{range = any_r(), other = true}. --spec any_range() -> #range{}. +-spec any_range() -> range(). any_range() -> - #range{range=any_r(), other=false}. + #range{range = any_r(), other = false}. --spec none_range() -> #range{}. +-spec none_range() -> range(). none_range() -> - #range{range=empty, other=true}. + #range{range = empty, other = true}. --spec none_type() -> #range{}. +-spec none_type() -> range(). none_type() -> #range{range = empty, other = false}. @@ -976,12 +978,12 @@ none_type() -> any_r() -> {neg_inf, pos_inf}. --spec get_range_from_args([argument()]) -> [#range{}]. +-spec get_range_from_args([argument()]) -> [range()]. get_range_from_args(Args) -> [get_range_from_arg(Arg) || Arg <- Args]. --spec get_range_from_arg(argument()) -> #range{}. +-spec get_range_from_arg(argument()) -> range(). get_range_from_arg(Arg) -> case hipe_icode:is_const(Arg) of @@ -989,15 +991,15 @@ get_range_from_arg(Arg) -> Value = hipe_icode:const_value(Arg), case is_integer(Value) of true -> - #range{range={Value,Value}, other=false}; + #range{range = {Value, Value}, other = false}; false -> - #range{range=empty, other=true} + #range{range = empty, other = true} end; false -> case hipe_icode:is_annotated_variable(Arg) of true -> case hipe_icode:variable_annotation(Arg) of - {range_anno, #ann{range=Range}, _} -> + {range_anno, #ann{range = Range}, _} -> Range; {type_anno, Type, _} -> range_from_simple_type(Type) @@ -1012,7 +1014,7 @@ get_range_from_arg(Arg) -> %% inf([R1,R2|Rest]) -> %% inf([inf(R1,R2)|Rest]). --spec inf(#range{}, #range{}) -> #range{}. +-spec inf(range(), range()) -> range(). inf(#range{range=R1, other=O1}, #range{range=R2, other=O2}) -> #range{range=range_inf(R1,R2), other=other_inf(O1,O2)}. @@ -1022,8 +1024,8 @@ inf(#range{range=R1, other=O1}, #range{range=R2, other=O2}) -> range_inf(empty, _) -> empty; range_inf(_, empty) -> empty; range_inf({Min1,Max1}, {Min2,Max2}) -> - NewMin = inf_max([Min1,Min2]), - NewMax = inf_min([Max1,Max2]), + NewMin = inf_max([Min1, Min2]), + NewMax = inf_min([Max1, Max2]), case inf_geq(NewMax, NewMin) of true -> {NewMin, NewMax}; @@ -1035,14 +1037,14 @@ range_inf({Min1,Max1}, {Min2,Max2}) -> other_inf(O1, O2) -> O1 and O2. --spec sup([#range{},...]) -> #range{}. +-spec sup([range(),...]) -> range(). sup([R]) -> R; sup([R1,R2|Rest]) -> sup([sup(R1, R2)|Rest]). --spec sup(#range{}, #range{}) -> #range{}. +-spec sup(range(), range()) -> range(). sup(#range{range=R1,other=O1}, #range{range=R2,other=O2}) -> #range{range=range_sup(R1,R2), other=other_sup(O1,O2)}. @@ -1063,7 +1065,7 @@ other_sup(O1, O2) -> O1 or O2. %%== Call Support ============================================================= -spec analyse_call_or_enter_fun(fun_name(), [argument()], - icode_call_type(), call_fun()) -> [#range{}]. + icode_call_type(), call_fun()) -> [range()]. analyse_call_or_enter_fun(Fun, Args, CallType, LookupFun) -> %%io:format("Fun: ~p~n Args: ~p~n CT: ~p~n LF: ~p~n", [Fun, Args, CallType, LookupFun]), @@ -1105,19 +1107,19 @@ analyse_call_or_enter_fun(Fun, Args, CallType, LookupFun) -> [any_type()]; {hipe_bs_primop, {bs_get_integer, Size, Flags}} -> {Min, Max} = analyse_bs_get_integer(Size, Flags, length(Args) =:= 1), - [#range{range={Min, Max}, other=false}, any_type()]; + [#range{range = {Min, Max}, other = false}, any_type()]; {hipe_bs_primop, _} = Primop -> Type = hipe_icode_primops:type(Primop), range_from_type(Type) end. --type bin_operation() :: fun((#range{},#range{}) -> #range{}). --type unary_operation() :: fun((#range{}) -> #range{}). +-type bin_operation() :: fun((range(), range()) -> range()). +-type unary_operation() :: fun((range()) -> range()). -spec basic_type(fun_name()) -> 'not_int' | 'not_analysed' - | {bin, bin_operation()} - | {unary, unary_operation()} - | {fcall, mfa()} | {hipe_bs_primop, _}. + | {'bin', bin_operation()} + | {'unary', unary_operation()} + | {'fcall', mfa()} | {'hipe_bs_primop', _}. %% Arithmetic operations basic_type('+') -> {bin, fun(R1, R2) -> range_add(R1, R2) end}; @@ -1214,7 +1216,7 @@ analyse_bs_get_integer(Size, Flags, false) when is_integer(Size), %% Arithmetic --spec range_add(#range{}, #range{}) -> #range{}. +-spec range_add(range(), range()) -> range(). range_add(Range1, Range2) -> NewMin = inf_add(range__min(Range1), range__min(Range2)), @@ -1222,7 +1224,7 @@ range_add(Range1, Range2) -> Other = other(Range1) orelse other(Range2), range_init({NewMin, NewMax}, Other). --spec range_sub(#range{}, #range{}) -> #range{}. +-spec range_sub(range(), range()) -> range(). range_sub(Range1, Range2) -> Min_sub = inf_min([inf_inv(range__max(Range2)), @@ -1234,7 +1236,7 @@ range_sub(Range1, Range2) -> Other = other(Range1) orelse other(Range2), range_init({NewMin, NewMax}, Other). --spec range_mult(#range{}, #range{}) -> #range{}. +-spec range_mult(range(), range()) -> range(). range_mult(#range{range=empty, other=true}, _Range2) -> range_init(empty, true); @@ -1274,7 +1276,7 @@ range_mult(Range1, Range2) -> Other = other(Range1) orelse other(Range2), range_init(Range, Other). --spec extreme_divisors(#range{}) -> range_tuple(). +-spec extreme_divisors(range()) -> range_tuple(). extreme_divisors(#range{range={0,0}}) -> {0,0}; extreme_divisors(#range{range={0,Max}}) -> {1,Max}; @@ -1289,7 +1291,7 @@ extreme_divisors(#range{range={Min,Max}}) -> end end. --spec range_div(#range{}, #range{}) -> #range{}. +-spec range_div(range(), range()) -> range(). %% this is div, not /. range_div(_, #range{range={0,0}}) -> @@ -1306,7 +1308,7 @@ range_div(Range1, Den) -> inf_div(Max1, Min2), inf_div(Max1, Max2)], range_init({inf_min(Min_max_list), inf_max(Min_max_list)}, false). --spec range_rem(#range{}, #range{}) -> #range{}. +-spec range_rem(range(), range()) -> range(). range_rem(Range1, Range2) -> %% Range1 desides the sign of the answer. @@ -1332,7 +1334,7 @@ range_rem(Range1, Range2) -> %%--- Bit operations ---------------------------- --spec range_bsr(#range{}, #range{}) -> #range{}. +-spec range_bsr(range(), range()) -> range(). range_bsr(Range1, Range2=#range{range={Min, Max}}) -> New_Range2 = range_init({inf_inv(Max), inf_inv(Min)}, other(Range2)), @@ -1340,7 +1342,7 @@ range_bsr(Range1, Range2=#range{range={Min, Max}}) -> %% io:format("bsr res:~w~nInput:= ~w~n", [Ans, {Range1,Range2}]), Ans. --spec range_bsl(#range{}, #range{}) -> #range{}. +-spec range_bsl(range(), range()) -> range(). range_bsl(Range1, Range2) -> Min1 = range__min(Range1), @@ -1359,7 +1361,7 @@ range_bsl(Range1, Range2) -> end, range_init(MinMax, false). --spec range_bnot(#range{}) -> #range{}. +-spec range_bnot(range()) -> range(). range_bnot(Range) -> Minus_one = range_init({-1,-1}, false), @@ -1389,7 +1391,7 @@ negwidth(X, N) -> false -> negwidth(X, N+1) end. --spec range_band(#range{}, #range{}) -> #range{}. +-spec range_band(range(), range()) -> range(). range_band(R1, R2) -> {_Min1, Max1} = MM1 = range(R1), @@ -1423,7 +1425,7 @@ range_band(R1, R2) -> end, range_init(Range, false). --spec range_bor(#range{}, #range{}) -> #range{}. +-spec range_bor(range(), range()) -> range(). range_bor(R1, R2) -> {Min1, _Max1} = MM1 = range(R1), @@ -1457,7 +1459,7 @@ range_bor(R1, R2) -> end, range_init(Range, false). --spec classify_range(#range{}) -> 'minus_minus' | 'minus_plus' | 'plus_plus'. +-spec classify_range(range()) -> 'minus_minus' | 'minus_plus' | 'plus_plus'. classify_range(Range) -> case range(Range) of @@ -1480,7 +1482,7 @@ classify_int_range(_Number1, Number2) when Number2 < 0 -> classify_int_range(_Number1, _Number2) -> minus_plus. --spec range_bxor(#range{}, #range{}) -> #range{}. +-spec range_bxor(range(), range()) -> range(). range_bxor(R1, R2) -> {Min1, Max1} = MM1 = range(R1), @@ -1895,7 +1897,7 @@ convert_ann_to_types(#ann{range=#range{other=true}, type=Type}) -> %% Icode Coordinator Callbacks %%===================================================================== --spec replace_nones([#range{}]) -> [#range{}]. +-spec replace_nones([range()]) -> [range()]. replace_nones(Args) -> [replace_none(Arg) || Arg <- Args]. @@ -1905,7 +1907,7 @@ replace_none(Arg) -> false -> Arg end. --spec update__info([#range{}], [#range{}]) -> {boolean(), [#ann{}]}. +-spec update__info([range()], [range()]) -> {boolean(), [ann()]}. update__info(NewRanges, OldRanges) -> SupFun = fun (Ann, Range) -> join_info(Ann, Range, fun safe_widen/3) @@ -1915,19 +1917,19 @@ update__info(NewRanges, OldRanges) -> Change = lists:zipwith(EqFun, ResRanges, OldRanges), {lists:all(fun (X) -> X end, Change), ResRanges}. --spec new__info/1 :: ([#range{}]) -> [#ann{}]. +-spec new__info([range()]) -> [ann()]. new__info(NewRanges) -> [#ann{range=Range,count=1,type=t_any()} || Range <- NewRanges]. --spec return__info/1 :: ([#ann{}]) -> [#range{}]. +-spec return__info([ann()]) -> [range()]. return__info(Ranges) -> [Range || #ann{range=Range} <- Ranges]. --spec return_none/0 :: () -> [#range{},...]. +-spec return_none() -> [range(),...]. return_none() -> [none_type()]. --spec return_none_args/2 :: (#cfg{}, mfa()) -> [#range{}]. +-spec return_none_args(cfg(), mfa()) -> [range()]. return_none_args(Cfg, {_M,_F,A}) -> NoArgs = case hipe_icode_cfg:is_closure(Cfg) of @@ -1936,7 +1938,7 @@ return_none_args(Cfg, {_M,_F,A}) -> end, lists:duplicate(NoArgs, none_type()). --spec return_any_args/2 :: (#cfg{}, mfa()) -> [#range{}]. +-spec return_any_args(cfg(), mfa()) -> [range()]. return_any_args(Cfg, {_M,_F,A}) -> NoArgs = case hipe_icode_cfg:is_closure(Cfg) of diff --git a/lib/hipe/main/hipe_main.erl b/lib/hipe/main/hipe_main.erl index e81642fb33..99028cc3c1 100644 --- a/lib/hipe/main/hipe_main.erl +++ b/lib/hipe/main/hipe_main.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -313,7 +313,7 @@ icode_ssa_struct_reuse(IcodeSSA, Options) -> icode_ssa_type_info(IcodeSSA, MFA, Options, Servers) -> ?option_time(hipe_icode_type:cfg(IcodeSSA, MFA, Options, Servers), - "Icode SSA type info", Options). + io_lib:format("Icode SSA type info for ~p", [MFA]), Options). icode_range_analysis(IcodeSSA, MFA, Options, Servers) -> case proplists:get_bool(icode_range, Options) of @@ -527,6 +527,8 @@ rtl_to_native(MFA, LinearRTL, Options, DebugState) -> hipe_sparc_main:rtl_to_sparc(MFA, LinearRTL, Options); powerpc -> hipe_ppc_main:rtl_to_ppc(MFA, LinearRTL, Options); + ppc64 -> + hipe_ppc_main:rtl_to_ppc(MFA, LinearRTL, Options); arm -> hipe_arm_main:rtl_to_arm(MFA, LinearRTL, Options); x86 -> diff --git a/lib/hipe/ppc/hipe_ppc.erl b/lib/hipe/ppc/hipe_ppc.erl index 047e86c45b..4014fc1561 100644 --- a/lib/hipe/ppc/hipe_ppc.erl +++ b/lib/hipe/ppc/hipe_ppc.erl @@ -1,20 +1,20 @@ %% -*- erlang-indent-level: 2 -*- %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2004-2011. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -58,6 +58,10 @@ mk_blr/0, mk_cmp/3, + cmpop_word/0, + cmpiop_word/0, + cmplop_word/0, + cmpliop_word/0, mk_comment/1, @@ -73,6 +77,8 @@ mk_loadx/4, mk_load/6, ldop_to_ldxop/1, + ldop_word/0, + ldop_wordx/0, mk_mfspr/2, @@ -110,6 +116,8 @@ mk_storex/4, mk_store/6, stop_to_stxop/1, + stop_word/0, + stop_wordx/0, mk_unary/3, @@ -189,6 +197,31 @@ mk_blr() -> #blr{}. mk_cmp(CmpOp, Src1, Src2) -> #cmp{cmpop=CmpOp, src1=Src1, src2=Src2}. +cmpop_word() -> + case get(hipe_target_arch) of + powerpc -> 'cmp'; + ppc64 -> 'cmpd' + end. + +cmpiop_word() -> + case get(hipe_target_arch) of + powerpc -> 'cmpi'; + ppc64 -> 'cmpdi' + end. + +cmplop_word() -> + case get(hipe_target_arch) of + powerpc -> 'cmpl'; + ppc64 -> 'cmpld' + end. + +cmpliop_word() -> + case get(hipe_target_arch) of + powerpc -> 'cmpli'; + ppc64 -> 'cmpldi' + end. + + mk_comment(Term) -> #comment{term=Term}. mk_label(Label) -> #label{label=Label}. @@ -198,9 +231,50 @@ label_label(#label{label=Label}) -> Label. %%% Load an integer constant into a register. mk_li(Dst, Value) -> mk_li(Dst, Value, []). -mk_li(Dst, Value, Tail) -> +mk_li(Dst, Value, Tail) -> % Dst can be R0 R0 = mk_temp(0, 'untagged'), - mk_addi(Dst, R0, Value, Tail). + %% Check if immediate can fit in the 32 bits, this is obviously a + %% sufficient check for PPC32 + if Value >= -16#80000000, + Value =< 16#7FFFFFFF -> + mk_li32(Dst, R0, Value, Tail); + true -> + Highest = (Value bsr 48), % Value@highest + Higher = (Value bsr 32) band 16#FFFF, % Value@higher + High = (Value bsr 16) band 16#FFFF, % Value@h + Low = Value band 16#FFFF, % Value@l + LdLo = + case Low of + 0 -> Tail; + _ -> [mk_alu('ori', Dst, Dst, mk_uimm16(Low)) | Tail] + end, + Ld32bits = + case High of + 0 -> LdLo; + _ -> [mk_alu('oris', Dst, Dst, mk_uimm16(High)) | LdLo] + end, + [mk_alu('addis', Dst, R0, mk_simm16(Highest)), + mk_alu('ori', Dst, Dst, mk_uimm16(Higher)), + mk_alu('sldi', Dst, Dst, mk_uimm16(32)) | + Ld32bits] + end. + +mk_li32(Dst, R0, Value, Tail) -> + case at_ha(Value) of + 0 -> + %% Value[31:16] are the sign-extension of Value[15]. + %% Use a single addi to load and sign-extend 16 bits. + [mk_alu('addi', Dst, R0, mk_simm16(at_l(Value))) | Tail]; + _ -> + %% Use addis to load the high 16 bits, followed by an + %% optional ori to load non sign-extended low 16 bits. + High = simm16sext((Value bsr 16) band 16#FFFF), + [mk_alu('addis', Dst, R0, mk_simm16(High)) | + case (Value band 16#FFFF) of + 0 -> Tail; + Low -> [mk_alu('ori', Dst, Dst, mk_uimm16(Low)) | Tail] + end] + end. mk_addi(Dst, R0, Value, Tail) -> Low = at_l(Value), @@ -232,27 +306,6 @@ simm16sext(Value) -> true -> Value end. -mk_li_new(Dst, Value, Tail) -> % Dst may be R0 - R0 = mk_temp(0, 'untagged'), - case at_ha(Value) of - 0 -> - %% Value[31:16] are the sign-extension of Value[15]. - %% Use a single addi to load and sign-extend 16 bits. - [mk_alu('addi', Dst, R0, mk_simm16(at_l(Value))) | - Tail]; - _ -> - %% Use addis to load the high 16 bits, followed by an - %% optional ori to load non sign-extended low 16 bits. - High = simm16sext((Value bsr 16) band 16#FFFF), - [mk_alu('addis', Dst, R0, mk_simm16(High)) | - case (Value band 16#FFFF) of - 0 -> Tail; - Low -> - [mk_alu('ori', Dst, Dst, mk_uimm16(Low)) | - Tail] - end] - end. - mk_load(LDop, Dst, Disp, Base) -> #load{ldop=LDop, dst=Dst, disp=Disp, base=Base}. @@ -260,8 +313,15 @@ mk_loadx(LdxOp, Dst, Base1, Base2) -> #loadx{ldxop=LdxOp, dst=Dst, base1=Base1, base2=Base2}. mk_load(LdOp, Dst, Offset, Base, Scratch, Rest) when is_integer(Offset) -> - if Offset >= -32768, Offset =< 32767 -> - [mk_load(LdOp, Dst, Offset, Base) | Rest]; + RequireAlignment = + case LdOp of + 'ld' -> true; + 'ldx' -> true; + _ -> false + end, + if Offset >= -32768, Offset =< 32767, + not RequireAlignment orelse Offset band 3 =:= 0 -> + [mk_load(LdOp, Dst, Offset, Base) | Rest]; true -> LdxOp = ldop_to_ldxop(LdOp), Index = @@ -272,8 +332,8 @@ mk_load(LdOp, Dst, Offset, Base, Scratch, Rest) when is_integer(Offset) -> true -> mk_scratch(Scratch) end end, - mk_li_new(Index, Offset, - [mk_loadx(LdxOp, Dst, Base, Index) | Rest]) + mk_li(Index, Offset, + [mk_loadx(LdxOp, Dst, Base, Index) | Rest]) end. ldop_to_ldxop(LdOp) -> @@ -281,7 +341,21 @@ ldop_to_ldxop(LdOp) -> 'lbz' -> 'lbzx'; 'lha' -> 'lhax'; 'lhz' -> 'lhzx'; - 'lwz' -> 'lwzx' + 'lwa' -> 'lwax'; + 'lwz' -> 'lwzx'; + 'ld' -> 'ldx' + end. + +ldop_word() -> + case get(hipe_target_arch) of + powerpc -> 'lwz'; + ppc64 -> 'ld' + end. + +ldop_wordx() -> + case get(hipe_target_arch) of + powerpc -> 'lwzx'; + ppc64 -> 'ldx' end. mk_scratch(Scratch) -> @@ -354,20 +428,40 @@ mk_storex(StxOp, Src, Base1, Base2) -> #storex{stxop=StxOp, src=Src, base1=Base1, base2=Base2}. mk_store(StOp, Src, Offset, Base, Scratch, Rest)when is_integer(Offset) -> - if Offset >= -32768, Offset =< 32767 -> + RequireAlignment = + case StOp of + 'std' -> true; + 'stdx' -> true; + _ -> false + end, + if Offset >= -32768, Offset =< 32767, + not RequireAlignment orelse Offset band 3 =:= 0 -> [mk_store(StOp, Src, Offset, Base) | Rest]; true -> StxOp = stop_to_stxop(StOp), Index = mk_scratch(Scratch), - mk_li_new(Index, Offset, - [mk_storex(StxOp, Src, Base, Index) | Rest]) + mk_li(Index, Offset, + [mk_storex(StxOp, Src, Base, Index) | Rest]) end. stop_to_stxop(StOp) -> case StOp of 'stb' -> 'stbx'; 'sth' -> 'sthx'; - 'stw' -> 'stwx' + 'stw' -> 'stwx'; + 'std' -> 'stdx' + end. + +stop_word() -> + case get(hipe_target_arch) of + powerpc -> 'stw'; + ppc64 -> 'std' + end. + +stop_wordx() -> + case get(hipe_target_arch) of + powerpc -> 'stwx'; + ppc64 -> 'stdx' end. mk_unary(UnOp, Dst, Src) -> #unary{unop=UnOp, dst=Dst, src=Src}. @@ -379,7 +473,7 @@ mk_fload(Dst, Offset, Base, Scratch) when is_integer(Offset) -> [mk_lfd(Dst, Offset, Base)]; true -> Index = mk_scratch(Scratch), - mk_li_new(Index, Offset, [mk_lfdx(Dst, Base, Index)]) + mk_li(Index, Offset, [mk_lfdx(Dst, Base, Index)]) end. mk_stfd(Src, Disp, Base) -> #stfd{src=Src, disp=Disp, base=Base}. @@ -389,7 +483,7 @@ mk_fstore(Src, Offset, Base, Scratch) when is_integer(Offset) -> [mk_stfd(Src, Offset, Base)]; true -> Index = mk_scratch(Scratch), - mk_li_new(Index, Offset, [mk_stfdx(Src, Base, Index)]) + mk_li(Index, Offset, [mk_stfdx(Src, Base, Index)]) end. mk_fp_binary(FpBinOp, Dst, Src1, Src2) -> diff --git a/lib/hipe/ppc/hipe_ppc_assemble.erl b/lib/hipe/ppc/hipe_ppc_assemble.erl index 6f06f8b841..b2fd50517b 100644 --- a/lib/hipe/ppc/hipe_ppc_assemble.erl +++ b/lib/hipe/ppc/hipe_ppc_assemble.erl @@ -1,20 +1,20 @@ %% -*- erlang-indent-level: 2 -*- %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2004-2011. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -39,7 +39,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, hipe_rtl_arch:word_size()), %% {CodeSize,CodeBinary,AccRefs,LabelMap,ExportMap} = encode(translate(Code, ConstMap), Options), @@ -159,6 +159,13 @@ do_alu(I) -> 'srwi.' -> {'rlwinm.', do_srwi_opnds(NewDst, NewSrc1, NewSrc2)}; 'srawi' -> {'srawi', {NewDst,NewSrc1,do_srawi_src2(NewSrc2)}}; 'srawi.' -> {'srawi.', {NewDst,NewSrc1,do_srawi_src2(NewSrc2)}}; + %ppc64 extension + 'sldi' -> {'rldicr', do_sldi_opnds(NewDst, NewSrc1, NewSrc2)}; + 'sldi.' -> {'rldicr.', do_sldi_opnds(NewDst, NewSrc1, NewSrc2)}; + 'srdi' -> {'rldicl', do_srdi_opnds(NewDst, NewSrc1, NewSrc2)}; + 'srdi.' -> {'rldicl.', do_srdi_opnds(NewDst, NewSrc1, NewSrc2)}; + 'sradi' -> {'sradi', {NewDst,NewSrc1,do_sradi_src2(NewSrc2)}}; + 'sradi.' -> {'sradi.', {NewDst,NewSrc1,do_sradi_src2(NewSrc2)}}; _ -> {AluOp, {NewDst,NewSrc1,NewSrc2}} end, [{NewI, NewOpnds, I}]. @@ -171,6 +178,15 @@ do_srwi_opnds(Dst, Src1, {uimm,N}) when is_integer(N), 0 =< N, N < 32 -> do_srawi_src2({uimm,N}) when is_integer(N), 0 =< N, N < 32 -> {sh,N}. +%% ppc64 extension +do_sldi_opnds(Dst, Src1, {uimm,N}) when is_integer(N), 0 =< N, N < 64 -> + {Dst, Src1, {sh6,N}, {me6,63-N}}. + +do_srdi_opnds(Dst, Src1, {uimm,N}) when is_integer(N), 0 =< N, N < 64 -> + {Dst, Src1, {sh6,64-N}, {mb6,N}}. + +do_sradi_src2({uimm,N}) when is_integer(N), 0 =< N, N < 64 -> {sh6,N}. + do_b_fun(I) -> #b_fun{'fun'=Fun,linkage=Linkage} = I, [{'.reloc', {b_fun,Fun,Linkage}, #comment{term='fun'}}, @@ -205,7 +221,18 @@ do_cmp(I) -> #cmp{cmpop=CmpOp,src1=Src1,src2=Src2} = I, NewSrc1 = do_reg(Src1), NewSrc2 = do_reg_or_imm(Src2), - [{CmpOp, {{crf,0},0,NewSrc1,NewSrc2}, I}]. + {RealOp,L} = + case CmpOp of + 'cmpd' -> {'cmp',1}; + 'cmpdi' -> {'cmpi',1}; + 'cmpld' -> {'cmpl',1}; + 'cmpldi' -> {'cmpli',1}; + 'cmp' -> {CmpOp,0}; + 'cmpi' -> {CmpOp,0}; + 'cmpl' -> {CmpOp,0}; + 'cmpli' -> {CmpOp,0} + end, + [{RealOp, {{crf,0},L,NewSrc1,NewSrc2}, I}]. do_label(I) -> #label{label=Label} = I, @@ -214,7 +241,12 @@ do_label(I) -> do_load(I) -> #load{ldop=LdOp,dst=Dst,disp=Disp,base=Base} = I, NewDst = do_reg(Dst), - NewDisp = do_disp(Disp), + NewDisp = + case LdOp of + 'ld' -> do_disp_ds(Disp); + 'ldu' -> do_disp_ds(Disp); + _ -> do_disp(Disp) + end, NewBase = do_reg(Base), [{LdOp, {NewDst,NewDisp,NewBase}, I}]. @@ -265,14 +297,30 @@ do_pseudo_li(I, MFA, ConstMap) -> end, NewDst = do_reg(Dst), Simm0 = {simm,0}, - [{'.reloc', RelocData, #comment{term=reloc}}, - {addi, {NewDst,{r,0},Simm0}, I}, - {addis, {NewDst,NewDst,Simm0}, I}]. + Uimm0 = {uimm,0}, + case get(hipe_target_arch) of + powerpc -> + [{'.reloc', RelocData, #comment{term=reloc}}, + {addi, {NewDst,{r,0},Simm0}, I}, + {addis, {NewDst,NewDst,Simm0}, I}]; + ppc64 -> + [{'.reloc', RelocData, #comment{term=reloc}}, + {addis, {NewDst,{r,0},Simm0}, I}, % @highest + {ori, {NewDst,NewDst,Uimm0}, I}, % @higher + {rldicr, {NewDst,NewDst,{sh6,32},{me6,31}}, I}, + {oris, {NewDst,NewDst,Uimm0}, I}, % @h + {ori, {NewDst,NewDst,Uimm0}, I}] % @l + end. do_store(I) -> #store{stop=StOp,src=Src,disp=Disp,base=Base} = I, NewSrc = do_reg(Src), - NewDisp = do_disp(Disp), + NewDisp = + case StOp of + 'std' -> do_disp_ds(Disp); + 'stdu' -> do_disp_ds(Disp); + _ -> do_disp(Disp) + end, NewBase = do_reg(Base), [{StOp, {NewSrc,NewDisp,NewBase}, I}]. @@ -344,6 +392,10 @@ do_reg_or_imm(Src) -> do_disp(Disp) when is_integer(Disp), -32768 =< Disp, Disp =< 32767 -> {d, Disp band 16#ffff}. +do_disp_ds(Disp) when is_integer(Disp), + -32768 =< Disp, Disp =< 32767, Disp band 3 =:= 0 -> + {ds, (Disp band 16#ffff) bsr 2}. + do_spr(SPR) -> SPR_NR = case SPR of diff --git a/lib/hipe/ppc/hipe_ppc_frame.erl b/lib/hipe/ppc/hipe_ppc_frame.erl index 158009872f..8a4d1906c0 100644 --- a/lib/hipe/ppc/hipe_ppc_frame.erl +++ b/lib/hipe/ppc/hipe_ppc_frame.erl @@ -1,20 +1,20 @@ %% -*- erlang-indent-level: 2 -*- %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2004-2011. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -103,12 +103,12 @@ do_pseudo_move(I, Context, FPoff) -> case temp_is_pseudo(Dst) of true -> Offset = pseudo_offset(Dst, FPoff, Context), - mk_store('stw', Src, Offset, mk_sp(), []); + mk_store(hipe_ppc:stop_word(), Src, Offset, mk_sp(), []); _ -> case temp_is_pseudo(Src) of true -> Offset = pseudo_offset(Src, FPoff, Context), - mk_load('lwz', Dst, Offset, mk_sp(), []); + mk_load(hipe_ppc:ldop_word(), Dst, Offset, mk_sp(), []); _ -> [hipe_ppc:mk_alu('or', Dst, Src, Src)] end @@ -152,7 +152,7 @@ restore_lr(FPoff, Context, Rest) -> false -> Rest; true -> Temp = mk_temp1(), - mk_load('lwz', Temp, FPoff - word_size(), mk_sp(), + mk_load(hipe_ppc:ldop_word(), Temp, FPoff - word_size(), mk_sp(), [hipe_ppc:mk_mtspr('lr', Temp) | Rest]) end. @@ -324,8 +324,8 @@ simple_moves([{SrcOff,DstOff,Type}|Moves], FPoff, TempReg, Rest) -> LoadOff = FPoff+SrcOff, StoreOff = FPoff+DstOff, simple_moves(Moves, FPoff, TempReg, - mk_load('lwz', Temp, LoadOff, SP, - mk_store('stw', Temp, StoreOff, SP, + mk_load(hipe_ppc:ldop_word(), Temp, LoadOff, SP, + mk_store(hipe_ppc:stop_word(), Temp, StoreOff, SP, Rest))); simple_moves([], _, _, Rest) -> Rest. @@ -343,7 +343,8 @@ store_moves([{Src,DstOff}|Moves], FPoff, TempReg, Rest) -> {Temp, hipe_ppc:mk_li(Temp, Src)} end, store_moves(Moves, FPoff, TempReg, - FixSrc ++ mk_store('stw', NewSrc, StoreOff, SP, Rest)); + FixSrc ++ mk_store(hipe_ppc:stop_word(), NewSrc, + StoreOff, SP, Rest)); store_moves([], _, _, Rest) -> Rest. @@ -400,7 +401,7 @@ mk_temp_map(Formals, ClobbersLR, Temps) -> enter_vars([V|Vs], PrevOff, Map) -> Off = case hipe_ppc:temp_type(V) of - 'double' -> PrevOff - 2*word_size(); + 'double' -> PrevOff - 8; _ -> PrevOff - word_size() end, enter_vars(Vs, Off, tmap_bind(Map, V, Off)); @@ -454,7 +455,8 @@ do_prologue(CFG, Context) -> AllocFrameCodeTail = case ClobbersLR of false -> GotoOldStartCode; - true -> mk_store('stw', Temp1, FrameSize-word_size(), SP, GotoOldStartCode) + true -> mk_store(hipe_ppc:stop_word(), Temp1, + FrameSize-word_size(), SP, GotoOldStartCode) end, %% Arity = context_arity(Context), @@ -484,7 +486,7 @@ do_prologue(CFG, Context) -> true -> [hipe_ppc:mk_mfspr(Temp1, 'lr') | NewStartCodeTail2] end, NewStartCode0 = - [hipe_ppc:mk_load('lwz', Temp1, ?P_NSP_LIMIT, P) | + [hipe_ppc:mk_load(hipe_ppc:ldop_word(), Temp1, ?P_NSP_LIMIT, P) | hipe_ppc:mk_addi(Temp2, SP, -MaxStack, [hipe_ppc:mk_cmp('cmpl', Temp2, Temp1) | NewStartCodeTail1])], diff --git a/lib/hipe/ppc/hipe_rtl_to_ppc.erl b/lib/hipe/ppc/hipe_rtl_to_ppc.erl index 458af250de..7dfa56df29 100644 --- a/lib/hipe/ppc/hipe_rtl_to_ppc.erl +++ b/lib/hipe/ppc/hipe_rtl_to_ppc.erl @@ -1,20 +1,20 @@ %%% -*- erlang-indent-level: 2 -*- %%% %%% %CopyrightBegin% -%%% -%%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%%% +%%% +%%% Copyright Ericsson AB 2004-2011. All Rights Reserved. +%%% %%% The contents of this file are subject to the Erlang Public License, %%% Version 1.1, (the "License"); you may not use this file except in %%% compliance with the License. You should have received a copy of the %%% Erlang Public License along with this software. If not, it can be %%% retrieved online at http://www.erlang.org/. -%%% +%%% %%% Software distributed under the License is distributed on an "AS IS" %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% the License for the specific language governing rights and limitations %%% under the License. -%%% +%%% %%% %CopyrightEnd% %%% %%% The PowerPC instruction set is quite irregular. @@ -110,20 +110,27 @@ conv_fconv(I, Map, Data) -> mk_fconv(Dst, Src) -> CSP = hipe_ppc:mk_temp(1, 'untagged'), - R0 = hipe_ppc:mk_temp(0, 'untagged'), - RTmp1 = hipe_ppc:mk_new_temp('untagged'), - RTmp2 = hipe_ppc:mk_new_temp('untagged'), - RTmp3 = hipe_ppc:mk_new_temp('untagged'), - FTmp1 = hipe_ppc:mk_new_temp('double'), - FTmp2 = hipe_ppc:mk_new_temp('double'), - [hipe_ppc:mk_pseudo_li(RTmp1, {fconv_constant,c_const}), - hipe_ppc:mk_lfd(FTmp1, 0, RTmp1), - hipe_ppc:mk_alu('xoris', RTmp2, Src, hipe_ppc:mk_uimm16(16#8000)), - hipe_ppc:mk_store('stw', RTmp2, 28, CSP), - hipe_ppc:mk_alu('addis', RTmp3, R0, hipe_ppc:mk_simm16(16#4330)), - hipe_ppc:mk_store('stw', RTmp3, 24, CSP), - hipe_ppc:mk_lfd(FTmp2, 24, CSP), - hipe_ppc:mk_fp_binary('fsub', Dst, FTmp2, FTmp1)]. + case get(hipe_target_arch) of + powerpc -> + R0 = hipe_ppc:mk_temp(0, 'untagged'), + RTmp1 = hipe_ppc:mk_new_temp('untagged'), + RTmp2 = hipe_ppc:mk_new_temp('untagged'), + RTmp3 = hipe_ppc:mk_new_temp('untagged'), + FTmp1 = hipe_ppc:mk_new_temp('double'), + FTmp2 = hipe_ppc:mk_new_temp('double'), + [hipe_ppc:mk_pseudo_li(RTmp1, {fconv_constant,c_const}), + hipe_ppc:mk_lfd(FTmp1, 0, RTmp1), + hipe_ppc:mk_alu('xoris', RTmp2, Src, hipe_ppc:mk_uimm16(16#8000)), + hipe_ppc:mk_store('stw', RTmp2, 28, CSP), + hipe_ppc:mk_alu('addis', RTmp3, R0, hipe_ppc:mk_simm16(16#4330)), + hipe_ppc:mk_store('stw', RTmp3, 24, CSP), + hipe_ppc:mk_lfd(FTmp2, 24, CSP), + hipe_ppc:mk_fp_binary('fsub', Dst, FTmp2, FTmp1)]; + ppc64 -> + [hipe_ppc:mk_store('std', Src, 24, CSP), + hipe_ppc:mk_lfd(Dst, 24, CSP), + hipe_ppc:mk_fp_unary('fcfid', Dst, Dst)] + end. conv_fmove(I, Map, Data) -> %% Dst := Src, where both Dst and Src are FP regs @@ -280,10 +287,14 @@ mk_alu_ri(Dst, Src1, RtlAluOp, Src2) -> 'mul' -> % 'mulli' has a 16-bit simm operand mk_alu_ri_simm16(Dst, Src1, RtlAluOp, 'mulli', Src2); 'and' -> % 'andi.' has a 16-bit uimm operand - case rlwinm_mask(Src2) of - {MB,ME} -> - [hipe_ppc:mk_unary({'rlwinm',0,MB,ME}, Dst, Src1)]; - _ -> + if Src2 band (bnot 16#ffffffff) =:= 0 -> + case rlwinm_mask(Src2) of + {MB,ME} -> + [hipe_ppc:mk_unary({'rlwinm',0,MB,ME}, Dst, Src1)]; + _ -> + mk_alu_ri_bitop(Dst, Src1, RtlAluOp, 'andi.', Src2) + end; + true -> mk_alu_ri_bitop(Dst, Src1, RtlAluOp, 'andi.', Src2) end; 'or' -> % 'ori' has a 16-bit uimm operand @@ -360,17 +371,33 @@ mk_alu_ri_bitop(Dst, Src1, RtlAluOp, AluOp, Src2) -> end. mk_alu_ri_shift(Dst, Src1, RtlAluOp, Src2) -> - if Src2 < 32, Src2 >= 0 -> - AluOp = - case RtlAluOp of - 'sll' -> 'slwi'; % alias for rlwinm - 'srl' -> 'srwi'; % alias for rlwinm - 'sra' -> 'srawi' - end, - [hipe_ppc:mk_alu(AluOp, Dst, Src1, - hipe_ppc:mk_uimm16(Src2))]; - true -> - mk_alu_ri_rr(Dst, Src1, RtlAluOp, Src2) + case get(hipe_target_arch) of + ppc64 -> + if Src2 < 64, Src2 >= 0 -> + AluOp = + case RtlAluOp of + 'sll' -> 'sldi'; % alias for rldimi %%% buggy + 'srl' -> 'srdi'; % alias for rldimi %%% buggy + 'sra' -> 'sradi' %%% buggy + end, + [hipe_ppc:mk_alu(AluOp, Dst, Src1, + hipe_ppc:mk_uimm16(Src2))]; + true -> + mk_alu_ri_rr(Dst, Src1, RtlAluOp, Src2) + end; + powerpc -> + if Src2 < 32, Src2 >= 0 -> + AluOp = + case RtlAluOp of + 'sll' -> 'slwi'; % alias for rlwinm + 'srl' -> 'srwi'; % alias for rlwinm + 'sra' -> 'srawi' + end, + [hipe_ppc:mk_alu(AluOp, Dst, Src1, + hipe_ppc:mk_uimm16(Src2))]; + true -> + mk_alu_ri_rr(Dst, Src1, RtlAluOp, Src2) + end end. mk_alu_ri_rr(Dst, Src1, RtlAluOp, Src2) -> @@ -384,15 +411,21 @@ mk_alu_rr(Dst, Src1, RtlAluOp, Src2) -> [hipe_ppc:mk_alu('subf', Dst, Src2, Src1)]; _ -> AluOp = - case RtlAluOp of - 'add' -> 'add'; - 'mul' -> 'mullw'; - 'or' -> 'or'; - 'and' -> 'and'; - 'xor' -> 'xor'; - 'sll' -> 'slw'; - 'srl' -> 'srw'; - 'sra' -> 'sraw' + case {get(hipe_target_arch), RtlAluOp} of + {_, 'add'} -> 'add'; + {_, 'or'} -> 'or'; + {_, 'and'} -> 'and'; + {_, 'xor'} -> 'xor'; + + {powerpc, 'mul'} -> 'mullw'; + {powerpc, 'sll'} -> 'slw'; + {powerpc, 'srl'} -> 'srw'; + {powerpc, 'sra'} -> 'sraw'; + + {ppc64, 'mul'} -> 'mulld'; + {ppc64, 'sll'} -> 'sld'; + {ppc64, 'srl'} -> 'srd'; + {ppc64, 'sra'} -> 'srad' end, [hipe_ppc:mk_alu(AluOp, Dst, Src1, Src2)] end. @@ -431,16 +464,22 @@ conv_alub(I, Map, Data) -> {I1 ++ I2, Map2, Data}. conv_alub_op(RtlAluOp) -> - case RtlAluOp of - 'add' -> 'add'; - 'sub' -> 'subf'; % XXX: must swap operands - 'mul' -> 'mullw'; - 'or' -> 'or'; - 'and' -> 'and'; - 'xor' -> 'xor'; - 'sll' -> 'slw'; - 'srl' -> 'srw'; - 'sra' -> 'sraw' + case {get(hipe_target_arch), RtlAluOp} of + {_, 'add'} -> 'add'; + {_, 'sub'} -> 'subf'; % XXX: must swap operands + {_, 'or'} -> 'or'; + {_, 'and'} -> 'and'; + {_, 'xor'} -> 'xor'; + + {powerpc, 'mul'} -> 'mullw'; + {powerpc, 'sll'} -> 'slw'; + {powerpc, 'srl'} -> 'srw'; + {powerpc, 'sra'} -> 'sraw'; + + {ppc64, 'mul'} -> 'mulld'; + {ppc64, 'sll'} -> 'sld'; + {ppc64, 'srl'} -> 'srd'; + {ppc64, 'sra'} -> 'srad' end. aluop_commutes(AluOp) -> @@ -454,7 +493,11 @@ aluop_commutes(AluOp) -> 'xor' -> true; 'slw' -> false; 'srw' -> false; - 'sraw' -> false + 'sraw' -> false; + 'mulld' -> true; % ppc64 + 'sld' -> false; % ppc64 + 'srd' -> false; % ppc64 + 'srad' -> false % ppc64 end. conv_alub_cond(Cond) -> % only signed @@ -528,17 +571,24 @@ mk_alub_ri_Rc(Dst, Src1, AluOp, Src2) -> mk_alub_ri_Rc_addi(Dst, Src1, Src2, 'addic.', 'add.'); 'addc' -> % 'addic' has a 16-bit simm operand mk_alub_ri_Rc_addi(Dst, Src1, Src2, 'addic', 'addc'); - 'mullw' -> % there is no 'mulli.' + 'mullw' -> % there is no 'mulli.' mk_alub_ri_Rc_rr(Dst, Src1, 'mullw.', Src2); + 'mulld' -> % there is no 'mulli.' + mk_alub_ri_Rc_rr(Dst, Src1, 'mulld.', Src2); 'or' -> % there is no 'ori.' mk_alub_ri_Rc_rr(Dst, Src1, 'or.', Src2); 'xor' -> % there is no 'xori.' mk_alub_ri_Rc_rr(Dst, Src1, 'xor.', Src2); 'and' -> % 'andi.' has a 16-bit uimm operand - case rlwinm_mask(Src2) of - {MB,ME} -> - [hipe_ppc:mk_unary({'rlwinm.',0,MB,ME}, Dst, Src1)]; - _ -> + if + Src2 band (bnot 16#ffffffff) =:= 0 -> + case rlwinm_mask(Src2) of + {MB,ME} -> + [hipe_ppc:mk_unary({'rlwinm.',0,MB,ME}, Dst, Src1)]; + _ -> + mk_alub_ri_Rc_andi(Dst, Src1, Src2) + end; + true -> mk_alub_ri_Rc_andi(Dst, Src1, Src2) end; _ -> % shift ops have 5-bit uimm operands @@ -562,13 +612,16 @@ mk_alub_ri_Rc_andi(Dst, Src1, Src2) -> end. mk_alub_ri_Rc_shift(Dst, Src1, AluOp, Src2) -> - if Src2 < 32, Src2 >= 0 -> - AluOpIDot = - case AluOp of - 'slw' -> 'slwi.'; % alias for rlwinm. - 'srw' -> 'srwi.'; % alias for rlwinm. - 'sraw' -> 'srawi.' - end, + {AluOpIDot, MaxIShift} = + case AluOp of + 'slw' -> {'slwi.', 32}; % alias for rlwinm. + 'srw' -> {'srwi.', 32}; % alias for rlwinm. + 'sraw' -> {'srawi.', 32}; + 'sld' -> {'sldi.', 64}; + 'srd' -> {'srdi.', 64}; + 'srad' -> {'sradi.', 64} + end, + if Src2 < MaxIShift, Src2 >= 0 -> [hipe_ppc:mk_alu(AluOpIDot, Dst, Src1, hipe_ppc:mk_uimm16(Src2))]; true -> @@ -576,7 +629,10 @@ mk_alub_ri_Rc_shift(Dst, Src1, AluOp, Src2) -> case AluOp of 'slw' -> 'slw.'; 'srw' -> 'srw.'; - 'sraw' -> 'sraw.' + 'sraw' -> 'sraw.'; + 'sld' -> 'sld.'; + 'srd' -> 'srd.'; + 'srad' -> 'srad.' end, mk_alub_ri_Rc_rr(Dst, Src1, AluOpDot, Src2) end. @@ -598,8 +654,9 @@ mk_alub_rr_OE(Dst, Src1, AluOp, Src2) -> case AluOp of 'subf' -> 'subfo.'; 'add' -> 'addo.'; - 'mullw' -> 'mullwo.' - %% fail for addc, or, and, xor, slw, srw, sraw + 'mullw' -> 'mullwo.'; + 'mulld' -> 'mulldo.' + %% fail for addc, or, and, xor, slw, srw, sraw end, [hipe_ppc:mk_alu(AluOpODot, Dst, Src1, Src2)]. @@ -610,12 +667,16 @@ mk_alub_rr_Rc(Dst, Src1, AluOp, Src2) -> 'add' -> 'add.'; 'addc' -> 'addc'; % only interested in CA, no Rc needed 'mullw' -> 'mullw.'; + 'mulld' -> 'mulld.'; 'or' -> 'or.'; 'and' -> 'and.'; 'xor' -> 'xor.'; 'slw' -> 'slw.'; + 'sld' -> 'sld.'; 'srw' -> 'srw.'; - 'sraw' -> 'sraw.' + 'srd' -> 'srd.'; + 'sraw' -> 'sraw.'; + 'srad' -> 'srad.' end, [hipe_ppc:mk_alu(AluOpDot, Dst, Src1, Src2)]. @@ -682,17 +743,17 @@ mk_branch_ri(Src1, BCond, Sign, Src2, TrueLab, FalseLab, Pred) -> case Sign of 'signed' -> if is_integer(Src2), -32768 =< Src2, Src2 < 32768 -> - {[], hipe_ppc:mk_simm16(Src2), 'cmpi'}; + {[], hipe_ppc:mk_simm16(Src2), hipe_ppc:cmpiop_word()}; true -> Tmp = new_untagged_temp(), - {mk_li(Tmp, Src2), Tmp, 'cmp'} + {mk_li(Tmp, Src2), Tmp, hipe_ppc:cmpop_word()} end; 'unsigned' -> if is_integer(Src2), 0 =< Src2, Src2 < 65536 -> - {[], hipe_ppc:mk_uimm16(Src2), 'cmpli'}; + {[], hipe_ppc:mk_uimm16(Src2), hipe_ppc:cmpliop_word()}; true -> Tmp = new_untagged_temp(), - {mk_li(Tmp, Src2), Tmp, 'cmpl'} + {mk_li(Tmp, Src2), Tmp, hipe_ppc:cmplop_word()} end end, FixSrc2 ++ @@ -701,8 +762,8 @@ mk_branch_ri(Src1, BCond, Sign, Src2, TrueLab, FalseLab, Pred) -> mk_branch_rr(Src1, BCond, Sign, Src2, TrueLab, FalseLab, Pred) -> CmpOp = case Sign of - 'signed' -> 'cmp'; - 'unsigned' -> 'cmpl' + 'signed' -> hipe_ppc:cmpop_word(); + 'unsigned' -> hipe_ppc:cmplop_word() end, mk_cmp_bc(CmpOp, Src1, Src2, BCond, TrueLab, FalseLab, Pred). @@ -841,7 +902,7 @@ mk_store_args([Arg|Args], PrevOffset, Tail) -> Tmp = new_tagged_temp(), {Tmp, mk_li(Tmp, Arg)} end, - Store = hipe_ppc:mk_store('stw', Src, Offset, mk_sp()), + Store = hipe_ppc:mk_store(hipe_ppc:stop_word(), Src, Offset, mk_sp()), mk_store_args(Args, Offset, FixSrc ++ [Store | Tail]); mk_store_args([], _, Tail) -> Tail. @@ -883,25 +944,19 @@ conv_load(I, Map, Data) -> {I2, Map2, Data}. mk_load(Dst, Base1, Base2, LoadSize, LoadSign) -> - Rest = - case LoadSize of - byte -> - case LoadSign of - signed -> [hipe_ppc:mk_unary('extsb', Dst, Dst)]; - _ -> [] + {LdOp, Rest} = + case {LoadSize, LoadSign} of + {byte, signed} -> {'lbz', [hipe_ppc:mk_unary('extsb', Dst, Dst)]}; + {byte, unsigned} -> {'lbz', []}; + {int16, signed} -> {'lha', []}; + {int16, unsigned} -> {'lhz', []}; + {int32, signed} -> + case get(hipe_target_arch) of + powerpc -> {'lwz', []}; + ppc64 -> {'lwa', []} end; - _ -> [] - end, - LdOp = - case LoadSize of - byte -> 'lbz'; - int32 -> 'lwz'; - word -> 'lwz'; - int16 -> - case LoadSign of - signed -> 'lha'; - unsigned -> 'lhz' - end + {int32, unsigned} -> {'lwz', []}; + {word, _} -> {hipe_ppc:ldop_word(), []} end, case hipe_ppc:is_temp(Base1) of true -> @@ -980,7 +1035,7 @@ mk_store(Src, Base1, Base2, StoreSize) -> byte -> 'stb'; int16 -> 'sth'; int32 -> 'stw'; - word -> 'stw' + word -> hipe_ppc:stop_word() end, case hipe_ppc:is_temp(Src) of true -> @@ -1022,10 +1077,16 @@ conv_switch(I, Map, Data) -> JTabR = new_untagged_temp(), OffsetR = new_untagged_temp(), DestR = new_untagged_temp(), + ShiftInstruction = + case get(hipe_target_arch) of + powerpc -> 'slwi'; + ppc64 -> 'sldi' + end, I2 = [hipe_ppc:mk_pseudo_li(JTabR, {JTabLab,constant}), - hipe_ppc:mk_alu('slwi', OffsetR, IndexR, hipe_ppc:mk_uimm16(2)), - hipe_ppc:mk_loadx('lwzx', DestR, JTabR, OffsetR), + hipe_ppc:mk_alu(ShiftInstruction, OffsetR, IndexR, + hipe_ppc:mk_uimm16(log2_word_size())), + hipe_ppc:mk_loadx(hipe_ppc:ldop_wordx(), DestR, JTabR, OffsetR), hipe_ppc:mk_mtspr('ctr', DestR), hipe_ppc:mk_bctr(Labels)], {I2, Map1, NewData}. @@ -1247,3 +1308,6 @@ vmap_bind(Map, Key, Val) -> word_size() -> hipe_rtl_arch:word_size(). + +log2_word_size() -> + hipe_rtl_arch:log2_word_size(). diff --git a/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl b/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl index ce33af453a..6ba4ac814e 100644 --- a/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl +++ b/lib/hipe/regalloc/hipe_graph_coloring_regalloc.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in diff --git a/lib/hipe/rtl/hipe_rtl.erl b/lib/hipe/rtl/hipe_rtl.erl index d93f423f0c..29e9c8c8fe 100644 --- a/lib/hipe/rtl/hipe_rtl.erl +++ b/lib/hipe/rtl/hipe_rtl.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in diff --git a/lib/hipe/rtl/hipe_rtl_arch.erl b/lib/hipe/rtl/hipe_rtl_arch.erl index 2afdf4eb6b..22cda57a3a 100644 --- a/lib/hipe/rtl/hipe_rtl_arch.erl +++ b/lib/hipe/rtl/hipe_rtl_arch.erl @@ -1,20 +1,20 @@ %% -*- erlang-indent-level: 2 -*- %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -86,6 +86,8 @@ first_virtual_reg() -> hipe_sparc_registers:first_virtual(); powerpc -> hipe_ppc_registers:first_virtual(); + ppc64 -> + hipe_ppc_registers:first_virtual(); arm -> hipe_arm_registers:first_virtual(); x86 -> @@ -100,6 +102,8 @@ heap_pointer() -> % {GetHPInsn, HPReg, PutHPInsn} heap_pointer_from_reg(hipe_sparc_registers:heap_pointer()); powerpc -> heap_pointer_from_reg(hipe_ppc_registers:heap_pointer()); + ppc64 -> + heap_pointer_from_reg(hipe_ppc_registers:heap_pointer()); arm -> heap_pointer_from_reg(hipe_arm_registers:heap_pointer()); x86 -> @@ -143,6 +147,8 @@ heap_limit() -> % {GetHLIMITInsn, HLIMITReg} heap_limit_from_pcb(); powerpc -> heap_limit_from_pcb(); + ppc64 -> + heap_limit_from_pcb(); arm -> heap_limit_from_pcb(); x86 -> @@ -165,6 +171,8 @@ fcalls() -> % {GetFCallsInsn, FCallsReg, PutFCallsInsn} fcalls_from_pcb(); powerpc -> fcalls_from_pcb(); + ppc64 -> + fcalls_from_pcb(); arm -> fcalls_from_pcb(); x86 -> @@ -188,6 +196,8 @@ reg_name(Reg) -> hipe_sparc_registers:reg_name_gpr(Reg); powerpc -> hipe_ppc_registers:reg_name_gpr(Reg); + ppc64 -> + hipe_ppc_registers:reg_name_gpr(Reg); arm -> hipe_arm_registers:reg_name_gpr(Reg); x86 -> @@ -215,6 +225,8 @@ is_precolored_regnum(RegNum) -> hipe_sparc_registers:is_precoloured_gpr(RegNum); powerpc -> hipe_ppc_registers:is_precoloured_gpr(RegNum); + ppc64 -> + hipe_ppc_registers:is_precoloured_gpr(RegNum); arm -> hipe_arm_registers:is_precoloured_gpr(RegNum); x86 -> @@ -243,6 +255,9 @@ live_at_return() -> powerpc -> ordsets:from_list([hipe_rtl:mk_reg(R) || {R,_} <- hipe_ppc_registers:live_at_return()]); + ppc64 -> + ordsets:from_list([hipe_rtl:mk_reg(R) + || {R,_} <- hipe_ppc_registers:live_at_return()]); arm -> ordsets:from_list([hipe_rtl:mk_reg(R) || {R,_} <- hipe_arm_registers:live_at_return()]); @@ -262,6 +277,7 @@ word_size() -> case get(hipe_target_arch) of ultrasparc -> 4; powerpc -> 4; + ppc64 -> 8; arm -> 4; x86 -> 4; amd64 -> 8 @@ -284,6 +300,7 @@ log2_word_size() -> case get(hipe_target_arch) of ultrasparc -> 2; powerpc -> 2; + ppc64 -> 3; arm -> 2; x86 -> 2; amd64 -> 3 @@ -297,6 +314,7 @@ endianess() -> case get(hipe_target_arch) of ultrasparc -> big; powerpc -> big; + ppc64 -> big; x86 -> little; amd64 -> little; arm -> ?ARM_ENDIANESS @@ -313,6 +331,8 @@ load_big_2(Dst, Base, Offset, Signedness) -> case get(hipe_target_arch) of powerpc -> load_2_directly(Dst, Base, Offset, Signedness); + ppc64 -> + load_2_directly(Dst, Base, Offset, Signedness); %% Note: x86 could use a "load;xchgb" or "load;rol $8,<16-bit reg>" %% sequence here. This has been implemented, but unfortunately didn't %% make consistent improvements to our benchmarks. @@ -333,6 +353,13 @@ load_little_2(Dst, Base, Offset, Signedness) -> unsigned -> []; signed -> [hipe_rtl:mk_call([Dst], 'extsh', [Dst], [], [], not_remote)] end]; + ppc64 -> + [hipe_rtl:mk_call([Dst], 'lhbrx', [Base,Offset], [], [], not_remote), + hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(2)) | + case Signedness of + unsigned -> []; + signed -> [hipe_rtl:mk_call([Dst], 'extsh', [Dst], [], [], not_remote)] + end]; _ -> load_little_2_in_pieces(Dst, Base, Offset, Signedness) end. @@ -365,6 +392,8 @@ load_big_4(Dst, Base, Offset, Signedness) -> case get(hipe_target_arch) of powerpc -> load_4_directly(Dst, Base, Offset, Signedness); + ppc64 -> + load_4_directly(Dst, Base, Offset, Signedness); %% Note: x86 could use a "load;bswap" sequence here. %% This has been implemented, but unfortunately didn't %% make any noticeable improvements in our benchmarks. @@ -386,6 +415,13 @@ load_little_4(Dst, Base, Offset, Signedness) -> powerpc -> [hipe_rtl:mk_call([Dst], 'lwbrx', [Base,Offset], [], [], not_remote), hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(4))]; + ppc64 -> + [hipe_rtl:mk_call([Dst], 'lwbrx', [Base,Offset], [], [], not_remote), + hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(4)) | + case Signedness of + unsigned -> []; + signed -> [hipe_rtl:mk_call([Dst], 'extsw', [Dst], [], [], not_remote)] + end]; arm -> %% When loading 4 bytes into a 32-bit register, the %% signedness of the high-order byte doesn't matter. @@ -396,7 +432,7 @@ load_little_4(Dst, Base, Offset, Signedness) -> end. load_4_directly(Dst, Base, Offset, Signedness) -> - [hipe_rtl:mk_load(Dst, Base, Offset, word, Signedness), + [hipe_rtl:mk_load(Dst, Base, Offset, int32, Signedness), hipe_rtl:mk_alu(Offset, Offset, add, hipe_rtl:mk_imm(4))]. load_big_4_in_pieces(Dst, Base, Offset, Signedness) -> @@ -440,6 +476,8 @@ store_4(Base, Offset, Src) -> store_4_directly(Base, Offset, Src); powerpc -> store_4_directly(Base, Offset, Src); + ppc64 -> + store_4_directly(Base, Offset, Src); arm -> store_big_4_in_pieces(Base, Offset, Src); ultrasparc -> @@ -525,6 +563,7 @@ fwait() -> amd64 -> [hipe_rtl:mk_call([], 'fwait', [], [], [], not_remote)]; arm -> []; powerpc -> []; + ppc64 -> []; ultrasparc -> [] end. @@ -549,6 +588,8 @@ handle_fp_exception() -> []; powerpc -> []; + ppc64 -> + []; ultrasparc -> [] end. @@ -577,6 +618,8 @@ proc_pointer() -> % must not be exported hipe_rtl:mk_reg_gcsafe(hipe_sparc_registers:proc_pointer()); powerpc -> hipe_rtl:mk_reg_gcsafe(hipe_ppc_registers:proc_pointer()); + ppc64 -> + hipe_rtl:mk_reg_gcsafe(hipe_ppc_registers:proc_pointer()); arm -> hipe_rtl:mk_reg_gcsafe(hipe_arm_registers:proc_pointer()); x86 -> @@ -601,6 +644,8 @@ nr_of_return_regs() -> %% hipe_sparc_registers:nr_rets(); powerpc -> 1; + ppc64 -> + 1; %% hipe_ppc_registers:nr_rets(); arm -> 1; diff --git a/lib/hipe/rtl/hipe_rtl_arith.inc b/lib/hipe/rtl/hipe_rtl_arith.inc index 9e80fa5e13..e608506234 100644 --- a/lib/hipe/rtl/hipe_rtl_arith.inc +++ b/lib/hipe/rtl/hipe_rtl_arith.inc @@ -3,7 +3,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% Copyright Ericsson AB 2004-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in diff --git a/lib/hipe/rtl/hipe_rtl_primops.erl b/lib/hipe/rtl/hipe_rtl_primops.erl index 0361053676..5f273d8251 100644 --- a/lib/hipe/rtl/hipe_rtl_primops.erl +++ b/lib/hipe/rtl/hipe_rtl_primops.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in diff --git a/lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl b/lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl index 64d723d15d..194cf29b64 100644 --- a/lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl +++ b/lib/hipe/rtl/hipe_rtl_ssa_const_prop.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% Copyright Ericsson AB 2004-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in diff --git a/lib/hipe/rtl/hipe_tagscheme.erl b/lib/hipe/rtl/hipe_tagscheme.erl index c0b6dfad8a..0cc6c2deec 100644 --- a/lib/hipe/rtl/hipe_tagscheme.erl +++ b/lib/hipe/rtl/hipe_tagscheme.erl @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. +%% Copyright Ericsson AB 2001-2011. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -1045,7 +1045,7 @@ convert_matchstate(Ms) -> build_sub_binary(Ms, ByteSize, ByteOffset, BitSize, BitOffset, hipe_rtl:mk_imm(0), Orig), size_from_header(SizeInWords, Header), - hipe_rtl:mk_alu(Hole, SizeInWords, sub, hipe_rtl:mk_imm(?SUB_BIN_WORDSIZE-1)), + hipe_rtl:mk_alu(Hole, SizeInWords, sub, hipe_rtl:mk_imm(?SUB_BIN_WORDSIZE)), mk_var_header(BigIntHeader, Hole, ?TAG_HEADER_POS_BIG), hipe_rtl:mk_store(Ms, hipe_rtl:mk_imm(?SUB_BIN_WORDSIZE*WordSize-?TAG_PRIMARY_BOXED), BigIntHeader)]. diff --git a/lib/hipe/vsn.mk b/lib/hipe/vsn.mk index fa9dc91ff0..6ba9009a24 100644 --- a/lib/hipe/vsn.mk +++ b/lib/hipe/vsn.mk @@ -1 +1 @@ -HIPE_VSN = 3.7.8 +HIPE_VSN = 3.7.9 |