From 6ce2fbadd41b657820276856299911470fb0a706 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 30 Sep 2016 19:34:45 +0200 Subject: hipe: TRY fix llvm external calls to own module to not be transformed to local calls. code_SUITE:uprade still fails if run with compile option {hipe,to_llvm} --- lib/hipe/llvm/hipe_llvm_main.erl | 17 +++++++---------- lib/hipe/llvm/hipe_rtl_to_llvm.erl | 29 +++++++++++++++++------------ 2 files changed, 24 insertions(+), 22 deletions(-) (limited to 'lib/hipe/llvm') diff --git a/lib/hipe/llvm/hipe_llvm_main.erl b/lib/hipe/llvm/hipe_llvm_main.erl index 476d6fb49c..164ccf20ef 100644 --- a/lib/hipe/llvm/hipe_llvm_main.erl +++ b/lib/hipe/llvm/hipe_llvm_main.erl @@ -257,15 +257,11 @@ fix_relocations(Relocs, RelocsDict, MFA) -> fix_reloc(#elf_rel{symbol=#elf_sym{name=Name, section=undefined, type=notype}, offset=Offset, type=?PCREL_T, addend=?PCREL_A}, - RelocsDict, {ModName,_,_}) when Name =/= "" -> + RelocsDict, {_,_,_}) when Name =/= "" -> case dict:fetch(Name, RelocsDict) of - {call, {bif, BifName, _}} -> {?CALL_LOCAL, Offset, BifName}; - %% MFA calls to functions in the same module are of type 3, while all - %% other MFA calls are of type 2. - %% XXX: Does this code break hot code loading (by transforming external - %% calls into local calls?) - {call, {ModName,_F,_A}=CallMFA} -> {?CALL_LOCAL, Offset, CallMFA}; - {call, CallMFA} -> {?CALL_REMOTE, Offset, CallMFA} + {call, _, {bif, BifName, _}} -> {?CALL_LOCAL, Offset, BifName}; + {call, not_remote, CallMFA} -> {?CALL_LOCAL, Offset, CallMFA}; + {call, remote, CallMFA} -> {?CALL_REMOTE, Offset, CallMFA} end; fix_reloc(#elf_rel{symbol=#elf_sym{name=Name, section=undefined, type=notype}, offset=Offset, type=?ABS_T, addend=?ABS_A}, @@ -280,7 +276,8 @@ fix_reloc(#elf_rel{symbol=#elf_sym{name=Name, section=#elf_shdr{name=?TEXT}, offset=Offset, type=?PCREL_T, addend=?PCREL_A}, RelocsDict, MFA) when Name =/= "" -> case dict:fetch(Name, RelocsDict) of - {call, MFA} -> {?CALL_LOCAL, Offset, MFA} + {call, not_remote, MFA} -> {?CALL_LOCAL, Offset, MFA}; + {call, remote, MFA} -> {?CALL_REMOTE, Offset, MFA} end; fix_reloc(#elf_rel{symbol=#elf_sym{name=Name, section=#elf_shdr{name=?RODATA}, type=object}, @@ -408,7 +405,7 @@ calls_with_stack_args(Dict) -> calls_with_stack_args(dict:to_list(Dict), []). calls_with_stack_args([], Calls) -> Calls; -calls_with_stack_args([ {_Name, {call, {M, F, A}}} | Rest], Calls) +calls_with_stack_args([ {_Name, {call, _, {M, F, A}}} | Rest], Calls) when A > ?NR_ARG_REGS -> Call = case M of diff --git a/lib/hipe/llvm/hipe_rtl_to_llvm.erl b/lib/hipe/llvm/hipe_rtl_to_llvm.erl index 66b2e10fb8..55ab6a3db1 100644 --- a/lib/hipe/llvm/hipe_rtl_to_llvm.erl +++ b/lib/hipe/llvm/hipe_rtl_to_llvm.erl @@ -257,7 +257,7 @@ trans_alub_overflow(I, Sign, Relocs) -> RtlDst = hipe_rtl:alub_dst(I), TmpDst = mk_temp(), Name = trans_alub_op(I, Sign), - NewRelocs = relocs_store(Name, {call, {llvm, Name, 2}}, Relocs), + NewRelocs = relocs_store(Name, {call, remote, {llvm, Name, 2}}, Relocs), WordTy = hipe_llvm:mk_int(?WORD_WIDTH), ReturnType = hipe_llvm:mk_struct([WordTy, hipe_llvm:mk_int(1)]), T1 = mk_temp(), @@ -364,7 +364,7 @@ trans_call(I, Relocs) -> {LoadedFixedRegs, I2} = load_fixed_regs(FixedRegs), FinalArgs = fix_reg_args(LoadedFixedRegs) ++ CallArgs, {Name, I3, Relocs2} = - trans_call_name(RtlCallName, Relocs1, CallArgs, FinalArgs), + trans_call_name(RtlCallName, hipe_rtl:call_type(I), Relocs1, CallArgs, FinalArgs), T1 = mk_temp(), WordTy = hipe_llvm:mk_int(?WORD_WIDTH), FunRetTy = hipe_llvm:mk_struct(lists:duplicate(?NR_PINNED_REGS + 1, WordTy)), @@ -430,17 +430,21 @@ expose_closure(CallName, CallArgs, Relocs) -> {[], Relocs} end. -trans_call_name(RtlCallName, Relocs, CallArgs, FinalArgs) -> +trans_call_name(RtlCallName, RtlCallType, Relocs, CallArgs, FinalArgs) -> case RtlCallName of PrimOp when is_atom(PrimOp) -> LlvmName = trans_prim_op(PrimOp), Relocs1 = - relocs_store(LlvmName, {call, {bif, PrimOp, length(CallArgs)}}, Relocs), + relocs_store(LlvmName, {call, not_remote, {bif, PrimOp, length(CallArgs)}}, Relocs), {"@" ++ LlvmName, [], Relocs1}; {M, F, A} when is_atom(M), is_atom(F), is_integer(A) -> LlvmName = trans_mfa_name({M, F, A}), + ok = case RtlCallType of + not_remote -> ok; + remote -> ok + end, Relocs1 = - relocs_store(LlvmName, {call, {M, F, length(CallArgs)}}, Relocs), + relocs_store(LlvmName, {call, RtlCallType, {M, F, length(CallArgs)}}, Relocs), {"@" ++ LlvmName, [], Relocs1}; Reg -> case hipe_rtl:is_reg(Reg) of @@ -501,7 +505,7 @@ trans_enter(I, Relocs) -> {LoadedFixedRegs, I1} = load_fixed_regs(FixedRegs), FinalArgs = fix_reg_args(LoadedFixedRegs) ++ CallArgs, {Name, I2, NewRelocs} = - trans_call_name(hipe_rtl:enter_fun(I), Relocs, CallArgs, FinalArgs), + trans_call_name(hipe_rtl:enter_fun(I), hipe_rtl:enter_type(I), Relocs, CallArgs, FinalArgs), T1 = mk_temp(), WordTy = hipe_llvm:mk_int(?WORD_WIDTH), FunRetTy = hipe_llvm:mk_struct(lists:duplicate(?NR_PINNED_REGS + 1, WordTy)), @@ -1457,9 +1461,9 @@ handle_relocations(Relocs, Data, Fun) -> Relocs2 = lists:foldl(fun const_to_dict/2, Relocs1, ConstLabels), %% Temporary Store inc_stack and llvm_fix_pinned_regs to Dictionary %% TODO: Remove this - Relocs3 = dict:store("inc_stack_0", {call, {bif, inc_stack_0, 0}}, Relocs2), + Relocs3 = dict:store("inc_stack_0", {call, remote, {bif, inc_stack_0, 0}}, Relocs2), Relocs4 = dict:store("hipe_bifs.llvm_fix_pinned_regs.0", - {call, {hipe_bifs, llvm_fix_pinned_regs, 0}}, Relocs3), + {call, remote, {hipe_bifs, llvm_fix_pinned_regs, 0}}, Relocs3), BranchMetaData = [ hipe_llvm:mk_meta(?BRANCH_META_TAKEN, ["branch_weights", 99, 1]) , hipe_llvm:mk_meta(?BRANCH_META_NOT_TAKEN, ["branch_weights", 1, 99]) @@ -1477,9 +1481,10 @@ seperate_relocs([], CallAcc, AtomAcc, ClosureAcc, LabelAcc, JmpTableAcc) -> {CallAcc, AtomAcc, ClosureAcc, LabelAcc, JmpTableAcc}; seperate_relocs([R|Rs], CallAcc, AtomAcc, ClosureAcc, LabelAcc, JmpTableAcc) -> case R of - {_, {call, _}} -> + {_, {call, _, _}} -> seperate_relocs(Rs, [R | CallAcc], AtomAcc, ClosureAcc, LabelAcc, JmpTableAcc); + {_, {atom, _}} -> seperate_relocs(Rs, CallAcc, [R | AtomAcc], ClosureAcc, LabelAcc, JmpTableAcc); @@ -1554,13 +1559,13 @@ declare_closure_labels(ClosureLabels, Relocs, Fun) -> hipe_llvm:mk_const_decl("@table_closures", "constant", TableType, List4), {[ConstDecl], Relocs1}. -%% @doc A call is treated as non external only in a case of a recursive +%% @doc A call is treated as non external only in a case of a local recursive %% function. -is_external_call({_, {call, Fun}}, Fun) -> false; +is_external_call({_, {call, _, MFA}}, MFA) -> false; is_external_call(_, _) -> true. %% @doc External declaration of a function. -call_to_decl({Name, {call, MFA}}) -> +call_to_decl({Name, {call, _, MFA}}) -> {M, _F, A} = MFA, CConv = "cc 11", WordTy = hipe_llvm:mk_int(?WORD_WIDTH), -- cgit v1.2.3 From c8f3ec52716064e0835e2e84329b2257be22acb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Tue, 18 Oct 2016 15:54:40 +0200 Subject: hipe_llvm: Use different symbols for remote calls --- lib/hipe/llvm/hipe_llvm_main.erl | 3 +-- lib/hipe/llvm/hipe_rtl_to_llvm.erl | 18 +++++++++++------- 2 files changed, 12 insertions(+), 9 deletions(-) (limited to 'lib/hipe/llvm') diff --git a/lib/hipe/llvm/hipe_llvm_main.erl b/lib/hipe/llvm/hipe_llvm_main.erl index 164ccf20ef..c8fc9cc856 100644 --- a/lib/hipe/llvm/hipe_llvm_main.erl +++ b/lib/hipe/llvm/hipe_llvm_main.erl @@ -276,8 +276,7 @@ fix_reloc(#elf_rel{symbol=#elf_sym{name=Name, section=#elf_shdr{name=?TEXT}, offset=Offset, type=?PCREL_T, addend=?PCREL_A}, RelocsDict, MFA) when Name =/= "" -> case dict:fetch(Name, RelocsDict) of - {call, not_remote, MFA} -> {?CALL_LOCAL, Offset, MFA}; - {call, remote, MFA} -> {?CALL_REMOTE, Offset, MFA} + {call, not_remote, MFA} -> {?CALL_LOCAL, Offset, MFA} end; fix_reloc(#elf_rel{symbol=#elf_sym{name=Name, section=#elf_shdr{name=?RODATA}, type=object}, diff --git a/lib/hipe/llvm/hipe_rtl_to_llvm.erl b/lib/hipe/llvm/hipe_rtl_to_llvm.erl index 55ab6a3db1..f5ea6d676f 100644 --- a/lib/hipe/llvm/hipe_rtl_to_llvm.erl +++ b/lib/hipe/llvm/hipe_rtl_to_llvm.erl @@ -438,7 +438,7 @@ trans_call_name(RtlCallName, RtlCallType, Relocs, CallArgs, FinalArgs) -> relocs_store(LlvmName, {call, not_remote, {bif, PrimOp, length(CallArgs)}}, Relocs), {"@" ++ LlvmName, [], Relocs1}; {M, F, A} when is_atom(M), is_atom(F), is_integer(A) -> - LlvmName = trans_mfa_name({M, F, A}), + LlvmName = trans_mfa_name({M, F, A}, RtlCallType), ok = case RtlCallType of not_remote -> ok; remote -> ok @@ -1039,8 +1039,12 @@ llvm_id(C) -> io_lib:format("_~2.16.0B_",[C]). %% @doc Create an acceptable LLVM identifier for an MFA. -trans_mfa_name({M,F,A}) -> - N = atom_to_list(M) ++ "." ++ atom_to_list(F) ++ "." ++ integer_to_list(A), +trans_mfa_name({M,F,A}, Linkage) -> + N0 = atom_to_list(M) ++ "." ++ atom_to_list(F) ++ "." ++ integer_to_list(A), + N = case Linkage of + not_remote -> N0; + remote -> "rem." ++ N0 + end, make_llvm_id(N). %%------------------------------------------------------------------------------ @@ -1342,7 +1346,7 @@ llvm_type_from_size(Size) -> %% precoloured registers that are passed as arguments must be stored to %% the corresonding stack slots. create_function_definition(Fun, Params, Code, LocalVars) -> - FunctionName = trans_mfa_name(Fun), + FunctionName = trans_mfa_name(Fun, not_remote), FixedRegs = fixed_registers(), %% Reverse parameters to match with the Erlang calling convention ReversedParams = @@ -1527,7 +1531,7 @@ load_closure({ClosureName, _})-> %% @doc Declaration of a local variable for a switch jump table. declare_switches(JumpTableList, Fun) -> - FunName = trans_mfa_name(Fun), + FunName = trans_mfa_name(Fun, not_remote), [declare_switch_table(X, FunName) || X <- JumpTableList]. declare_switch_table({Name, {switch, {TableType, Labels, _, _}, _}}, FunName) -> @@ -1543,7 +1547,7 @@ declare_switch_table({Name, {switch, {TableType, Labels, _, _}, _}}, FunName) -> declare_closure_labels([], Relocs, _Fun) -> {[], Relocs}; declare_closure_labels(ClosureLabels, Relocs, Fun) -> - FunName = trans_mfa_name(Fun), + FunName = trans_mfa_name(Fun, not_remote), {LabelList, ArityList} = lists:unzip([{mk_jump_label(Label), A} || {_, {closure_label, Label, A}} <- ClosureLabels]), @@ -1561,7 +1565,7 @@ declare_closure_labels(ClosureLabels, Relocs, Fun) -> %% @doc A call is treated as non external only in a case of a local recursive %% function. -is_external_call({_, {call, _, MFA}}, MFA) -> false; +is_external_call({_, {call, not_remote, MFA}}, MFA) -> false; is_external_call(_, _) -> true. %% @doc External declaration of a function. -- cgit v1.2.3 From a148265b865abbd001b308be9a6f79b68896306a Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 20 Oct 2016 15:11:12 +0200 Subject: hipe: Remove redundant assertion --- lib/hipe/llvm/hipe_rtl_to_llvm.erl | 4 ---- 1 file changed, 4 deletions(-) (limited to 'lib/hipe/llvm') diff --git a/lib/hipe/llvm/hipe_rtl_to_llvm.erl b/lib/hipe/llvm/hipe_rtl_to_llvm.erl index f5ea6d676f..44bd1ad9c5 100644 --- a/lib/hipe/llvm/hipe_rtl_to_llvm.erl +++ b/lib/hipe/llvm/hipe_rtl_to_llvm.erl @@ -439,10 +439,6 @@ trans_call_name(RtlCallName, RtlCallType, Relocs, CallArgs, FinalArgs) -> {"@" ++ LlvmName, [], Relocs1}; {M, F, A} when is_atom(M), is_atom(F), is_integer(A) -> LlvmName = trans_mfa_name({M, F, A}, RtlCallType), - ok = case RtlCallType of - not_remote -> ok; - remote -> ok - end, Relocs1 = relocs_store(LlvmName, {call, RtlCallType, {M, F, length(CallArgs)}}, Relocs), {"@" ++ LlvmName, [], Relocs1}; -- cgit v1.2.3 From f66a70f651c2889f69b938e7ad061bddb8fe2116 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 20 Oct 2016 15:14:05 +0200 Subject: hipe,llvm: Change inc_stack_0 bif call to not_remote Seems to work either way, it just seem more correct as all other 'bif' calls are 'not_remote'. --- lib/hipe/llvm/hipe_rtl_to_llvm.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/hipe/llvm') diff --git a/lib/hipe/llvm/hipe_rtl_to_llvm.erl b/lib/hipe/llvm/hipe_rtl_to_llvm.erl index 44bd1ad9c5..53aa8c57b2 100644 --- a/lib/hipe/llvm/hipe_rtl_to_llvm.erl +++ b/lib/hipe/llvm/hipe_rtl_to_llvm.erl @@ -1461,7 +1461,7 @@ handle_relocations(Relocs, Data, Fun) -> Relocs2 = lists:foldl(fun const_to_dict/2, Relocs1, ConstLabels), %% Temporary Store inc_stack and llvm_fix_pinned_regs to Dictionary %% TODO: Remove this - Relocs3 = dict:store("inc_stack_0", {call, remote, {bif, inc_stack_0, 0}}, Relocs2), + Relocs3 = dict:store("inc_stack_0", {call, not_remote, {bif, inc_stack_0, 0}}, Relocs2), Relocs4 = dict:store("hipe_bifs.llvm_fix_pinned_regs.0", {call, remote, {hipe_bifs, llvm_fix_pinned_regs, 0}}, Relocs3), BranchMetaData = [ -- cgit v1.2.3 From d5f0e614ab2998a153de569290bf2fca78d88af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Mon, 7 Nov 2016 17:37:22 +0100 Subject: hipe_llvm: Fix incorrect atom alignment assumption ErLLVM was declaring atoms in the following manner: @atom_ok = external constant i64 ; Used inside a function like this %var = ptrtoint i64* @atom_ok to i64 However, doing so makes LLVM think the `atom_ok` is 8-byte aligned, since it refers to a i64 value. This resulted in LLVM occasionally incorrectly optimising away type tests on atoms, causing incorrect behaviour or even segfaults. One such case is in bs_match_compiler:coverage_apply/2, in which an is_boxed test on a literal atom was optimised away, causing the code to try and load the "header" of an atom. This problem reproduces with LLVM versions 3.7 through 3.9. By declaring atoms as i8 (byte) constants instead, LLVM no longer makes these alignment assumptions, and the bug is fixed. --- lib/hipe/llvm/hipe_rtl_to_llvm.erl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'lib/hipe/llvm') diff --git a/lib/hipe/llvm/hipe_rtl_to_llvm.erl b/lib/hipe/llvm/hipe_rtl_to_llvm.erl index 66b2e10fb8..46201cb2ef 100644 --- a/lib/hipe/llvm/hipe_rtl_to_llvm.erl +++ b/lib/hipe/llvm/hipe_rtl_to_llvm.erl @@ -1496,16 +1496,18 @@ seperate_relocs([R|Rs], CallAcc, AtomAcc, ClosureAcc, LabelAcc, JmpTableAcc) -> %% @doc External declaration of an atom. declare_atom({AtomName, _}) -> - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), - hipe_llvm:mk_const_decl("@" ++ AtomName, "external constant", WordTy, ""). + %% The type has to be byte, or a backend might assume the constant is aligned + %% and incorrectly optimise away type tests + ByteTy = hipe_llvm:mk_int(8), + hipe_llvm:mk_const_decl("@" ++ AtomName, "external constant", ByteTy, ""). %% @doc Creation of local variable for an atom. load_atom({AtomName, _}) -> Dst = "%" ++ AtomName ++ "_var", Name = "@" ++ AtomName, WordTy = hipe_llvm:mk_int(?WORD_WIDTH), - WordTyPtr = hipe_llvm:mk_pointer(WordTy), - hipe_llvm:mk_conversion(Dst, ptrtoint, WordTyPtr, Name, WordTy). + ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(8)), + hipe_llvm:mk_conversion(Dst, ptrtoint, ByteTyPtr, Name, WordTy). %% @doc External declaration of a closure. declare_closure({ClosureName, _})-> -- cgit v1.2.3 From 537ae156bb024978094aa1a4827a0aec83c70459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Mon, 7 Nov 2016 17:50:22 +0100 Subject: hipe_llvm: Work around LLVM 3.9 sdesc bug As of LLVM 3.9, the x86-call-frame-opt pass in LLVM's X86 backend causes the stack descriptors to contain incorrect (or even negative) frame sizes or root slot offsets. This might cause LLVM-compiled modules to be rejected during loading with a badarg exception in hipe_bifs:enter_sdecs/1 (which additionally prints a "hipe_bifs_enter_sdesc_1: bad sdesc!" message to stderr), or it might cause corruption or segmentation faults when walking stacks (f.ex. during GC) containing frames compiled with ErLLVM. As a workaround, we pass the -no-x86-call-frame-opt flag to llc when the version is at least 3.9 --- lib/hipe/llvm/hipe_llvm_main.erl | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'lib/hipe/llvm') diff --git a/lib/hipe/llvm/hipe_llvm_main.erl b/lib/hipe/llvm/hipe_llvm_main.erl index 476d6fb49c..7f70826046 100644 --- a/lib/hipe/llvm/hipe_llvm_main.erl +++ b/lib/hipe/llvm/hipe_llvm_main.erl @@ -84,7 +84,7 @@ compile_with_llvm(FunName, Arity, LLVMCode, Options, UseBuffer) -> __ = file:close(File_llvm), %% Invoke LLVM compiler tools to produce an object file llvm_opt(Dir, Filename, Options), - llvm_llc(Dir, Filename, Options), + llvm_llc(Dir, Filename, Ver, Options), compile(Dir, Filename, "gcc"), %%FIXME: use llc -filetype=obj and skip this! {ok, Dir, Dir ++ Filename ++ ".o"}. @@ -103,12 +103,14 @@ llvm_opt(Dir, Filename, Options) -> %% @doc Invoke llc tool to compile the bitcode to object file %% (_name.bc -> _name.o). -llvm_llc(Dir, Filename, Options) -> +llvm_llc(Dir, Filename, Ver, Options) -> Source = Dir ++ Filename ++ ".bc", OptLevel = trans_optlev_flag(llc, Options), + VerFlags = llc_ver_flags(Ver), Align = find_stack_alignment(), LlcFlags = [OptLevel, "-code-model=medium", "-stack-alignment=" ++ Align - , "-tailcallopt", "-filetype=asm"], %%FIXME + , "-tailcallopt", "-filetype=asm" %FIXME + | VerFlags], Command = "llc " ++ fix_opts(LlcFlags) ++ " " ++ Source, %% io:format("LLC: ~s~n", [Command]), case os:cmd(Command) of @@ -153,6 +155,12 @@ trans_optlev_flag(Tool, Options) -> undefined -> "-O2" end. +llc_ver_flags(Ver = {_, _}) when Ver >= {3,9} -> + %% Works around a bug in the x86-call-frame-opt pass (as of LLVM 3.9) that + %% break the garbage collection stack descriptors. + ["-no-x86-call-frame-opt"]; +llc_ver_flags({_, _}) -> []. + %%------------------------------------------------------------------------------ %% Functions to manage Relocations %%------------------------------------------------------------------------------ -- cgit v1.2.3 From 24d1459d9daf1a8acfae34d32bd3b39fe33cfef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Tue, 8 Nov 2016 23:36:21 +0100 Subject: hipe_rtl_to_llvm: Constants for bits per byte/word The constant ?WORD_WIDTH is renamed ?BITS_IN_WORD, and a new constant ?BITS_IN_BYTE is introduced. Additionally, a bug in a currently unused case clause of llvm_type_from_size/1 is fixed (the size of a word was hardcoded to 64 bits). --- lib/hipe/llvm/hipe_rtl_to_llvm.erl | 97 +++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 48 deletions(-) (limited to 'lib/hipe/llvm') diff --git a/lib/hipe/llvm/hipe_rtl_to_llvm.erl b/lib/hipe/llvm/hipe_rtl_to_llvm.erl index 46201cb2ef..2179f7f765 100644 --- a/lib/hipe/llvm/hipe_rtl_to_llvm.erl +++ b/lib/hipe/llvm/hipe_rtl_to_llvm.erl @@ -10,7 +10,8 @@ -include("../rtl/hipe_literals.hrl"). -include("hipe_llvm_arch.hrl"). --define(WORD_WIDTH, (?bytes_to_bits(hipe_rtl_arch:word_size()))). +-define(BITS_IN_WORD, (?bytes_to_bits(hipe_rtl_arch:word_size()))). +-define(BITS_IN_BYTE, (?bytes_to_bits(1))). -define(BRANCH_META_TAKEN, "0"). -define(BRANCH_META_NOT_TAKEN, "1"). -define(FIRST_FREE_META_NO, 2). @@ -95,9 +96,9 @@ do_alloca_stack([], _, _, Acc) -> Acc; do_alloca_stack([D|Ds], Params, Roots, Acc) -> {Name, _I} = trans_dst(D), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), WordTyPtr = hipe_llvm:mk_pointer(WordTy), - ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(8)), + ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(?BITS_IN_BYTE)), case hipe_rtl:is_var(D) of true -> Num = hipe_rtl:var_index(D), @@ -233,7 +234,7 @@ trans_alu(I, Relocs) -> {Src1, I1} = trans_src(hipe_rtl:alu_src1(I)), {Src2, I2} = trans_src(hipe_rtl:alu_src2(I)), Op = trans_op(hipe_rtl:alu_op(I)), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), I3 = hipe_llvm:mk_operation(TmpDst, Op, WordTy, Src1, Src2, []), I4 = store_stack_dst(TmpDst, RtlDst), {[I4, I3, I2, I1], Relocs}. @@ -258,7 +259,7 @@ trans_alub_overflow(I, Sign, Relocs) -> TmpDst = mk_temp(), Name = trans_alub_op(I, Sign), NewRelocs = relocs_store(Name, {call, {llvm, Name, 2}}, Relocs), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), ReturnType = hipe_llvm:mk_struct([WordTy, hipe_llvm:mk_int(1)]), T1 = mk_temp(), I3 = hipe_llvm:mk_call(T1, false, [], [], ReturnType, "@" ++ Name, @@ -320,7 +321,7 @@ trans_alub_no_overflow(I, Relocs) -> {Dst, I2} = trans_src(hipe_rtl:alub_dst(I)), Cond = trans_rel_op(hipe_rtl:alub_cond(I)), T3 = mk_temp(), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), I5 = hipe_llvm:mk_icmp(T3, Cond, WordTy, Dst, "0"), %% br Metadata = branch_metadata(hipe_rtl:alub_pred(I)), @@ -338,7 +339,7 @@ trans_branch(I, Relocs) -> Cond = trans_rel_op(hipe_rtl:branch_cond(I)), %% icmp T1 = mk_temp(), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), I3 = hipe_llvm:mk_icmp(T1, Cond, WordTy, Src1, Src2), %% br True_label = mk_jump_label(hipe_rtl:branch_true_label(I)), @@ -366,7 +367,7 @@ trans_call(I, Relocs) -> {Name, I3, Relocs2} = trans_call_name(RtlCallName, Relocs1, CallArgs, FinalArgs), T1 = mk_temp(), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), FunRetTy = hipe_llvm:mk_struct(lists:duplicate(?NR_PINNED_REGS + 1, WordTy)), I4 = case hipe_rtl:call_fail(I) of @@ -450,7 +451,7 @@ trans_call_name(RtlCallName, Relocs, CallArgs, FinalArgs) -> %% order to make the call TT1 = mk_temp(), {RegName, II1} = trans_src(Reg), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), WordTyPtr = hipe_llvm:mk_pointer(WordTy), II2 = hipe_llvm:mk_conversion(TT1, inttoptr, WordTy, RegName, WordTyPtr), @@ -503,7 +504,7 @@ trans_enter(I, Relocs) -> {Name, I2, NewRelocs} = trans_call_name(hipe_rtl:enter_fun(I), Relocs, CallArgs, FinalArgs), T1 = mk_temp(), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), FunRetTy = hipe_llvm:mk_struct(lists:duplicate(?NR_PINNED_REGS + 1, WordTy)), I3 = hipe_llvm:mk_call(T1, true, "cc 11", [], FunRetTy, Name, FinalArgs, []), I4 = hipe_llvm:mk_ret([{FunRetTy, T1}]), @@ -518,7 +519,7 @@ trans_fconv(I, Relocs) -> TmpDst = mk_temp(), {Src, I1} = trans_float_src(hipe_rtl:fconv_src(I)), FloatTy = hipe_llvm:mk_double(), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), I2 = hipe_llvm:mk_conversion(TmpDst, sitofp, WordTy, Src, FloatTy), I3 = store_float_stack(TmpDst, RtlDst), {[I3, I2, I1], Relocs}. @@ -538,7 +539,7 @@ trans_fload(I, Relocs) -> {Src, I1} = trans_float_src(RtlSrc), {Offset, I2} = trans_float_src(_Offset), T1 = mk_temp(), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), FloatTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_double()), I3 = hipe_llvm:mk_operation(T1, add, WordTy, Src, Offset, []), T2 = mk_temp(), @@ -619,7 +620,7 @@ trans_fstore(I, Relocs) -> trans_fstore_reg(I, Relocs) -> {Base, I0} = trans_reg(hipe_rtl:fstore_base(I), dst), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), WordTyPtr = hipe_llvm:mk_pointer(WordTy), FloatTy = hipe_llvm:mk_double(), FloatTyPtr = hipe_llvm:mk_pointer(FloatTy), @@ -659,7 +660,7 @@ trans_load(I, Relocs) -> {Src, I1} = trans_src(hipe_rtl:load_src(I)), {Offset, I2} = trans_src(hipe_rtl:load_offset(I)), T1 = mk_temp(), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), WordTyPtr = hipe_llvm:mk_pointer(WordTy), I3 = hipe_llvm:mk_operation(T1, add, WordTy, Src, Offset, []), %%---------------------------------------------------------------- @@ -737,7 +738,7 @@ trans_move(I, Relocs) -> %% return %% trans_return(I, Relocs) -> - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), {VarRet, I1} = case hipe_rtl:return_varlist(I) of [] -> @@ -777,7 +778,7 @@ trans_store(I, Relocs) -> {Offset, I2} = trans_src(hipe_rtl:store_offset(I)), {Value, I3} = trans_src(hipe_rtl:store_src(I)), T1 = mk_temp(), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), WordTyPtr = hipe_llvm:mk_pointer(WordTy), I4 = hipe_llvm:mk_operation(T1, add, WordTy, Base, Offset, []), I5 = @@ -811,14 +812,14 @@ trans_switch(I, Relocs, Data) -> JumpLabels = [mk_jump_label(L) || L <- Labels], SortOrder = hipe_rtl:switch_sort_order(I), NrLabels = length(Labels), - ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(8)), + ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(?BITS_IN_BYTE)), TableType = hipe_llvm:mk_array(NrLabels, ByteTyPtr), TableTypeP = hipe_llvm:mk_pointer(TableType), TypedJumpLabels = [{hipe_llvm:mk_label_type(), X} || X <- JumpLabels], T1 = mk_temp(), {Src2, []} = trans_dst(RtlSrc), TableName = "table_" ++ tl(Src2), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), I2 = hipe_llvm:mk_getelementptr(T1, TableTypeP, "@"++TableName, [{WordTy, "0"}, {WordTy, Src}], false), T2 = mk_temp(), @@ -933,7 +934,7 @@ create_fail_blocks(Label, FailLabels, Acc) -> false -> Acc; {value, {Label, FailLabel, SpAdj}, RestFailLabels} -> - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), I1 = hipe_llvm:mk_label(FailLabel), LP = hipe_llvm:mk_landingpad(), I2 = @@ -962,7 +963,7 @@ create_fail_blocks(Label, FailLabels, Acc) -> %% @doc Convert RTL argument list to LLVM argument list. trans_args(ArgList) -> - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), MakeArg = fun(A) -> {Name, I1} = trans_src(A), @@ -972,13 +973,13 @@ trans_args(ArgList) -> %% @doc Convert a list of Precoloured registers to LLVM argument list. fix_reg_args(ArgList) -> - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), [{WordTy, A} || A <- ArgList]. %% @doc Load Precoloured registers. load_fixed_regs(RegList) -> Names = [mk_temp_reg(R) || R <- RegList], - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), WordTyPtr = hipe_llvm:mk_pointer(WordTy), Fun1 = fun (X, Y) -> @@ -991,7 +992,7 @@ load_fixed_regs(RegList) -> store_fixed_regs(RegList, Name) -> Names = [mk_temp_reg(R) || R <- RegList], Indexes = lists:seq(0, erlang:length(RegList) - 1), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), WordTyPtr = hipe_llvm:mk_pointer(WordTy), FunRetTy = hipe_llvm:mk_struct(lists:duplicate(?NR_PINNED_REGS + 1, WordTy)), Fun1 = @@ -1060,7 +1061,7 @@ mk_temp_reg(Name) -> store_stack_dst(TempDst, Dst) -> {Dst2, II1} = trans_dst(Dst), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), WordTyPtr = hipe_llvm:mk_pointer(WordTy), II2 = hipe_llvm:mk_store(WordTy, TempDst, WordTyPtr, Dst2, [], [], false), [II2, II1]. @@ -1078,7 +1079,7 @@ trans_float_src(Src) -> Name = "@DL" ++ integer_to_list(hipe_rtl:const_label_label(Src)), T1 = mk_temp(), %% XXX: Hardcoded offset - ByteTy = hipe_llvm:mk_int(8), + ByteTy = hipe_llvm:mk_int(?BITS_IN_BYTE), ByteTyPtr = hipe_llvm:mk_pointer(ByteTy), I1 = hipe_llvm:mk_getelementptr(T1, ByteTyPtr, Name, [{ByteTy, integer_to_list(?FLOAT_OFFSET)}], true), @@ -1094,7 +1095,7 @@ trans_float_src(Src) -> end. trans_src(A) -> - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), WordTyPtr = hipe_llvm:mk_pointer(WordTy), case hipe_rtl:is_imm(A) of true -> @@ -1197,7 +1198,7 @@ map_precoloured_reg(Index) -> fix_reg_dst(Register) -> case Register of {Name, Offset} -> %% Case of %fcalls, %hplim - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), pointer_from_reg(Name, WordTy, Offset); Name -> %% Case of %p and %hp {Name, []} @@ -1205,7 +1206,7 @@ fix_reg_dst(Register) -> %% @doc Load precoloured src register. fix_reg_src(Register) -> - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), WordTyPtr = hipe_llvm:mk_pointer(WordTy), case Register of {Name, Offset} -> %% Case of %fcalls, %hplim @@ -1327,10 +1328,10 @@ insn_dst(I) -> llvm_type_from_size(Size) -> case Size of - byte -> hipe_llvm:mk_int(8); + byte -> hipe_llvm:mk_int(?BITS_IN_BYTE); int16 -> hipe_llvm:mk_int(16); int32 -> hipe_llvm:mk_int(32); - word -> hipe_llvm:mk_int(64) + word -> hipe_llvm:mk_int(?BITS_IN_WORD) end. %% @doc Create definition for the compiled function. The parameters that are @@ -1360,13 +1361,13 @@ create_function_definition(Fun, Params, Code, LocalVars) -> lists:flatten([EntryLabel, ExceptionSync, I2, LocalVars, StoredParams, I3]), Final_Code = EntryBlock ++ Code, FunctionOptions = [nounwind, noredzone, list_to_atom("gc \"erlang\"")], - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), FunRetTy = hipe_llvm:mk_struct(lists:duplicate(?NR_PINNED_REGS + 1, WordTy)), hipe_llvm:mk_fun_def([], [], "cc 11", [], FunRetTy, FunctionName, Args, FunctionOptions, [], Final_Code). header_params(Params) -> - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), [{WordTy, "%v" ++ integer_to_list(hipe_rtl:var_index(P))} || P <- Params]. store_params(Params) -> @@ -1375,7 +1376,7 @@ store_params(Params) -> Index = hipe_rtl:var_index(X), {Name, _} = trans_dst(X), ParamName = "%v" ++ integer_to_list(Index), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), WordTyPtr = hipe_llvm:mk_pointer(WordTy), hipe_llvm:mk_store(WordTy, ParamName, WordTyPtr, Name, [], [], false) end, @@ -1392,11 +1393,11 @@ fixed_registers() -> end. header_regs(Registers) -> - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), [{WordTy, "%" ++ X ++ "_in"} || X <- Registers]. load_regs(Registers) -> - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), WordTyPtr = hipe_llvm:mk_pointer(WordTy), Fun1 = fun(X) -> @@ -1498,28 +1499,28 @@ seperate_relocs([R|Rs], CallAcc, AtomAcc, ClosureAcc, LabelAcc, JmpTableAcc) -> declare_atom({AtomName, _}) -> %% The type has to be byte, or a backend might assume the constant is aligned %% and incorrectly optimise away type tests - ByteTy = hipe_llvm:mk_int(8), + ByteTy = hipe_llvm:mk_int(?BITS_IN_BYTE), hipe_llvm:mk_const_decl("@" ++ AtomName, "external constant", ByteTy, ""). %% @doc Creation of local variable for an atom. load_atom({AtomName, _}) -> Dst = "%" ++ AtomName ++ "_var", Name = "@" ++ AtomName, - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), - ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(8)), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), + ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(?BITS_IN_BYTE)), hipe_llvm:mk_conversion(Dst, ptrtoint, ByteTyPtr, Name, WordTy). %% @doc External declaration of a closure. declare_closure({ClosureName, _})-> - ByteTy = hipe_llvm:mk_int(8), + ByteTy = hipe_llvm:mk_int(?BITS_IN_BYTE), hipe_llvm:mk_const_decl("@" ++ ClosureName, "external constant", ByteTy, ""). %% @doc Creation of local variable for a closure. load_closure({ClosureName, _})-> Dst = "%" ++ ClosureName ++ "_var", Name = "@" ++ ClosureName, - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), - ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(8)), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), + ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(?BITS_IN_BYTE)), hipe_llvm:mk_conversion(Dst, ptrtoint, ByteTyPtr, Name, WordTy). %% @doc Declaration of a local variable for a switch jump table. @@ -1550,7 +1551,7 @@ declare_closure_labels(ClosureLabels, Relocs, Fun) -> List3 = string:join(List2, ",\n"), List4 = "[\n" ++ List3 ++ "\n]\n", NrLabels = length(LabelList), - ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(8)), + ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(?BITS_IN_BYTE)), TableType = hipe_llvm:mk_array(NrLabels, ByteTyPtr), ConstDecl = hipe_llvm:mk_const_decl("@table_closures", "constant", TableType, List4), @@ -1565,7 +1566,7 @@ is_external_call(_, _) -> true. call_to_decl({Name, {call, MFA}}) -> {M, _F, A} = MFA, CConv = "cc 11", - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), FunRetTy = hipe_llvm:mk_struct(lists:duplicate(?NR_PINNED_REGS + 1, WordTy)), {Type, Args} = case M of @@ -1580,14 +1581,14 @@ call_to_decl({Name, {call, MFA}}) -> %% @doc These functions are always declared, even if not used. fixed_fun_decl() -> - ByteTy = hipe_llvm:mk_int(8), + ByteTy = hipe_llvm:mk_int(?BITS_IN_BYTE), ByteTyPtr = hipe_llvm:mk_pointer(ByteTy), LandPad = hipe_llvm:mk_fun_decl([], [], [], [], hipe_llvm:mk_int(32), "@__gcc_personality_v0", [hipe_llvm:mk_int(32), hipe_llvm:mk_int(64), ByteTyPtr, ByteTyPtr], []), GCROOTDecl = hipe_llvm:mk_fun_decl([], [], [], [], hipe_llvm:mk_void(), "@llvm.gcroot", [hipe_llvm:mk_pointer(ByteTyPtr), ByteTyPtr], []), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), FunRetTy = hipe_llvm:mk_struct(lists:duplicate(?NR_PINNED_REGS + 1, WordTy)), FixPinnedRegs = hipe_llvm:mk_fun_decl([], [], [], [], FunRetTy, "@hipe_bifs.llvm_fix_pinned_regs.0", [], []), @@ -1601,7 +1602,7 @@ fixed_fun_decl() -> %% values, add the offset and convert them again to pointers. declare_constant(Label) -> Name = "@DL" ++ integer_to_list(Label), - ByteTy = hipe_llvm:mk_int(8), + ByteTy = hipe_llvm:mk_int(?BITS_IN_BYTE), hipe_llvm:mk_const_decl(Name, "external constant", ByteTy, ""). %% @doc Load a constant is achieved by converting a pointer to an integer of @@ -1609,8 +1610,8 @@ declare_constant(Label) -> load_constant(Label) -> Dst = "%DL" ++ integer_to_list(Label) ++ "_var", Name = "@DL" ++ integer_to_list(Label), - WordTy = hipe_llvm:mk_int(?WORD_WIDTH), - ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(8)), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), + ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(?BITS_IN_BYTE)), hipe_llvm:mk_conversion(Dst, ptrtoint, ByteTyPtr, Name, WordTy). %% @doc Store external constants and calls to dictionary. -- cgit v1.2.3 From ca0fbe891d0f8278b4824d6b2c5db4cd01fcef5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Wed, 9 Nov 2016 18:46:19 +0100 Subject: hipe_rtl: unify branch and alub branch and alub overlap in their use cases, but the backends rely on knowing that the result is unused in their lowering of branch. By extending alub so that the destination is optional, it can fully replace branch. This simplifies rtl by reducing code duplication and the number of instructions. Also, in the x86 and arm backends, we can now use 'test' and {'tst','mvn','teq'} to lower some alubs without destinations. This is particularly good for x86, as sequences such as 'is_boxed' type tests now get shorter (both from not needing a mov to copy the variable, but also from the fact that 'testb' encodes shorter than 'andq'). --- lib/hipe/llvm/hipe_rtl_to_llvm.erl | 78 +++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 39 deletions(-) (limited to 'lib/hipe/llvm') diff --git a/lib/hipe/llvm/hipe_rtl_to_llvm.erl b/lib/hipe/llvm/hipe_rtl_to_llvm.erl index 20813f8bd7..f8911c1909 100644 --- a/lib/hipe/llvm/hipe_rtl_to_llvm.erl +++ b/lib/hipe/llvm/hipe_rtl_to_llvm.erl @@ -156,9 +156,6 @@ translate_instr(I, Relocs, Data) -> #alub{} -> {I2, Relocs2} = trans_alub(I, Relocs), {I2, Relocs2, Data}; - #branch{} -> - {I2, Relocs2} = trans_branch(I, Relocs), - {I2, Relocs2, Data}; #call{} -> {I2, Relocs2} = case hipe_rtl:call_fun(I) of @@ -255,7 +252,6 @@ trans_alub(I, Relocs) -> trans_alub_overflow(I, Sign, Relocs) -> {Src1, I1} = trans_src(hipe_rtl:alub_src1(I)), {Src2, I2} = trans_src(hipe_rtl:alub_src2(I)), - RtlDst = hipe_rtl:alub_dst(I), TmpDst = mk_temp(), Name = trans_alub_op(I, Sign), NewRelocs = relocs_store(Name, {call, remote, {llvm, Name, 2}}, Relocs), @@ -266,7 +262,10 @@ trans_alub_overflow(I, Sign, Relocs) -> [{WordTy, Src1}, {WordTy, Src2}], []), %% T1{0}: result of the operation I4 = hipe_llvm:mk_extractvalue(TmpDst, ReturnType, T1 , "0", []), - I5 = store_stack_dst(TmpDst, RtlDst), + I5 = case hipe_rtl:alub_has_dst(I) of + false -> []; + true -> store_stack_dst(TmpDst, hipe_rtl:alub_dst(I)) + end, T2 = mk_temp(), %% T1{1}: Boolean variable indicating overflow I6 = hipe_llvm:mk_extractvalue(T2, ReturnType, T1, "1", []), @@ -311,42 +310,35 @@ trans_alub_op(I, Sign) -> Name ++ Type. trans_alub_no_overflow(I, Relocs) -> + {Src1, I1} = trans_src(hipe_rtl:alub_src1(I)), + {Src2, I2} = trans_src(hipe_rtl:alub_src2(I)), + WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), %% alu - T = hipe_rtl:mk_alu(hipe_rtl:alub_dst(I), hipe_rtl:alub_src1(I), - hipe_rtl:alub_op(I), hipe_rtl:alub_src2(I)), - %% A trans_alu instruction cannot change relocations - {I1, _} = trans_alu(T, Relocs), + {CmpLhs, CmpRhs, I5, Cond} = + case {hipe_rtl:alub_has_dst(I), hipe_rtl:alub_op(I)} of + {false, 'sub'} -> + Cond0 = trans_branch_rel_op(hipe_rtl:alub_cond(I)), + {Src1, Src2, [], Cond0}; + {HasDst, AlubOp} -> + TmpDst = mk_temp(), + Op = trans_op(AlubOp), + I3 = hipe_llvm:mk_operation(TmpDst, Op, WordTy, Src1, Src2, []), + I4 = case HasDst of + false -> []; + true -> store_stack_dst(TmpDst, hipe_rtl:alub_dst(I)) + end, + Cond0 = trans_alub_rel_op(hipe_rtl:alub_cond(I)), + {TmpDst, "0", [I4, I3], Cond0} + end, %% icmp - %% Translate destination as src, to match with the semantics of instruction - {Dst, I2} = trans_src(hipe_rtl:alub_dst(I)), - Cond = trans_rel_op(hipe_rtl:alub_cond(I)), T3 = mk_temp(), - WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), - I5 = hipe_llvm:mk_icmp(T3, Cond, WordTy, Dst, "0"), + I6 = hipe_llvm:mk_icmp(T3, Cond, WordTy, CmpLhs, CmpRhs), %% br Metadata = branch_metadata(hipe_rtl:alub_pred(I)), True_label = mk_jump_label(hipe_rtl:alub_true_label(I)), False_label = mk_jump_label(hipe_rtl:alub_false_label(I)), - I6 = hipe_llvm:mk_br_cond(T3, True_label, False_label, Metadata), - {[I6, I5, I2, I1], Relocs}. - -%% -%% branch -%% -trans_branch(I, Relocs) -> - {Src1, I1} = trans_src(hipe_rtl:branch_src1(I)), - {Src2, I2} = trans_src(hipe_rtl:branch_src2(I)), - Cond = trans_rel_op(hipe_rtl:branch_cond(I)), - %% icmp - T1 = mk_temp(), - WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), - I3 = hipe_llvm:mk_icmp(T1, Cond, WordTy, Src1, Src2), - %% br - True_label = mk_jump_label(hipe_rtl:branch_true_label(I)), - False_label = mk_jump_label(hipe_rtl:branch_false_label(I)), - Metadata = branch_metadata(hipe_rtl:branch_pred(I)), - I4 = hipe_llvm:mk_br_cond(T1, True_label, False_label, Metadata), - {[I4, I3, I2, I1], Relocs}. + I7 = hipe_llvm:mk_br_cond(T3, True_label, False_label, Metadata), + {[I7, I6, I5, I2, I1], Relocs}. branch_metadata(X) when X =:= 0.5 -> []; branch_metadata(X) when X > 0.5 -> ?BRANCH_META_TAKEN; @@ -1162,7 +1154,7 @@ trans_dst(A) -> true -> "%DL" ++ integer_to_list(hipe_rtl:const_label_label(A)) ++ "_var"; false -> - exit({?MODULE, trans_dst, {"Bad RTL argument",A}}) + error(badarg, [A]) end end end, @@ -1260,14 +1252,19 @@ trans_op(Op) -> Other -> exit({?MODULE, trans_op, {"Unknown RTL operator", Other}}) end. -trans_rel_op(Op) -> +trans_branch_rel_op(Op) -> case Op of - eq -> eq; - ne -> ne; gtu -> ugt; geu -> uge; ltu -> ult; leu -> ule; + _ -> trans_alub_rel_op(Op) + end. + +trans_alub_rel_op(Op) -> + case Op of + eq -> eq; + ne -> ne; gt -> sgt; ge -> sge; lt -> slt; @@ -1300,7 +1297,10 @@ insn_dst(I) -> #alu{} -> [hipe_rtl:alu_dst(I)]; #alub{} -> - [hipe_rtl:alub_dst(I)]; + case hipe_rtl:alub_has_dst(I) of + true -> [hipe_rtl:alub_dst(I)]; + false -> [] + end; #call{} -> case hipe_rtl:call_dstlist(I) of [] -> []; -- cgit v1.2.3 From 5d373def7b8069eda8b6d1d2babd713933c6f472 Mon Sep 17 00:00:00 2001 From: Andrew Dryga Date: Tue, 14 Feb 2017 11:32:24 +0200 Subject: Fixed typos in lib/hipe --- lib/hipe/llvm/hipe_rtl_to_llvm.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/hipe/llvm') diff --git a/lib/hipe/llvm/hipe_rtl_to_llvm.erl b/lib/hipe/llvm/hipe_rtl_to_llvm.erl index f8911c1909..208d86841f 100644 --- a/lib/hipe/llvm/hipe_rtl_to_llvm.erl +++ b/lib/hipe/llvm/hipe_rtl_to_llvm.erl @@ -1431,7 +1431,7 @@ relocs_to_list(Relocs) -> %% constants/labels. handle_relocations(Relocs, Data, Fun) -> RelocsList = relocs_to_list(Relocs), - %% Seperate Relocations according to their type + %% Separate Relocations according to their type {CallList, AtomList, ClosureList, ClosureLabels, SwitchList} = seperate_relocs(RelocsList), %% Create code to declare atoms @@ -1474,7 +1474,7 @@ handle_relocations(Relocs, Data, Fun) -> LocalVariables = AtomLoad ++ ClosureLoad ++ ConstLoad, {Relocs4, ExternalDeclarations, LocalVariables}. -%% @doc Seperate relocations according to their type. +%% @doc Separate relocations according to their type. seperate_relocs(Relocs) -> seperate_relocs(Relocs, [], [], [], [], []). -- cgit v1.2.3 From 1aa3038dba459a61ac0dfcda016b323b6c74cf84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Sun, 19 Feb 2017 10:57:41 +0100 Subject: ErLLVM: Drop code printing assembly for LLVM < 3.9 --- lib/hipe/llvm/hipe_llvm.erl | 40 ++++++++++------------------------------ 1 file changed, 10 insertions(+), 30 deletions(-) (limited to 'lib/hipe/llvm') diff --git a/lib/hipe/llvm/hipe_llvm.erl b/lib/hipe/llvm/hipe_llvm.erl index b22f8fb320..641d3fda0a 100644 --- a/lib/hipe/llvm/hipe_llvm.erl +++ b/lib/hipe/llvm/hipe_llvm.erl @@ -862,7 +862,7 @@ pp_ins(Dev, Ver, I) -> true -> write(Dev, "volatile "); false -> ok end, - pp_dereference_type(Dev, Ver, load_p_type(I)), + pp_dereference_type(Dev, load_p_type(I)), write(Dev, [" ", load_pointer(I), " "]), case load_alignment(I) of [] -> ok; @@ -898,7 +898,7 @@ pp_ins(Dev, Ver, I) -> true -> write(Dev, "inbounds "); false -> ok end, - pp_dereference_type(Dev, Ver, getelementptr_p_type(I)), + pp_dereference_type(Dev, getelementptr_p_type(I)), write(Dev, [" ", getelementptr_value(I)]), pp_typed_idxs(Dev, getelementptr_typed_idxs(I)), write(Dev, "\n"); @@ -959,10 +959,8 @@ pp_ins(Dev, Ver, I) -> pp_args(Dev, fun_def_arglist(I)), write(Dev, ") "), pp_options(Dev, fun_def_fn_attrs(I)), - case Ver >= {3,7} of false -> ok; true -> - write(Dev, "personality i32 (i32, i64, i8*,i8*)* " - "@__gcc_personality_v0 ") - end, + write(Dev, "personality i32 (i32, i64, i8*,i8*)* " + "@__gcc_personality_v0 "), case fun_def_align(I) of [] -> ok; N -> write(Dev, ["align ", N]) @@ -997,12 +995,7 @@ pp_ins(Dev, Ver, I) -> pp_type(Dev, const_decl_type(I)), write(Dev, [" ", const_decl_value(I), "\n"]); #llvm_landingpad{} -> - write(Dev, "landingpad { i8*, i32 } "), - case Ver < {3,7} of false -> ok; true -> - write(Dev, "personality i32 (i32, i64, i8*,i8*)* " - "@__gcc_personality_v0 ") - end, - write(Dev, "cleanup\n"); + write(Dev, "landingpad { i8*, i32 } cleanup\n"); #llvm_asm{} -> write(Dev, [asm_instruction(I), "\n"]); #llvm_adj_stack{} -> @@ -1011,15 +1004,7 @@ pp_ins(Dev, Ver, I) -> pp_type(Dev, adj_stack_type(I)), write(Dev, [" ", adj_stack_offset(I),")\n"]); #llvm_meta{} -> - write(Dev, ["!", meta_id(I), " = "]), - Named = case string:to_integer(meta_id(I)) of - {_, ""} -> false; - _ -> true - end, - case Ver < {3,6} andalso not Named of - true -> write(Dev, "metadata !{metadata "); - false -> write(Dev, "!{ ") - end, + write(Dev, ["!", meta_id(I), " = !{ "]), write(Dev, string:join([if is_list(Op) -> ["!\"", Op, "\""]; is_integer(Op) -> ["i32 ", integer_to_list(Op)]; is_record(Op, llvm_meta) -> @@ -1030,15 +1015,10 @@ pp_ins(Dev, Ver, I) -> exit({?MODULE, pp_ins, {"Unknown LLVM instruction", Other}}) end. -%% @doc Print the type of a dereference in an LLVM instruction using syntax -%% parsable by the specified LLVM version. -pp_dereference_type(Dev, Ver, Type) -> - case Ver >= {3,7} of - false -> ok; - true -> - pp_type(Dev, pointer_type(Type)), - write(Dev, ", ") - end, +%% @doc Print the type of a dereference in an LLVM instruction. +pp_dereference_type(Dev, Type) -> + pp_type(Dev, pointer_type(Type)), + write(Dev, ", "), pp_type(Dev, Type). %% @doc Pretty-print a list of types -- cgit v1.2.3 From 9e2d61fa511c714f9f8cd2e5c57edf408ecf05e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Mon, 20 Feb 2017 15:02:32 +0100 Subject: hipe_rtl_to_llvm: Cleanup --- lib/hipe/llvm/hipe_rtl_to_llvm.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/hipe/llvm') diff --git a/lib/hipe/llvm/hipe_rtl_to_llvm.erl b/lib/hipe/llvm/hipe_rtl_to_llvm.erl index 208d86841f..79e1bfd381 100644 --- a/lib/hipe/llvm/hipe_rtl_to_llvm.erl +++ b/lib/hipe/llvm/hipe_rtl_to_llvm.erl @@ -1364,7 +1364,7 @@ create_function_definition(Fun, Params, Code, LocalVars) -> EntryBlock = lists:flatten([EntryLabel, ExceptionSync, I2, LocalVars, StoredParams, I3]), Final_Code = EntryBlock ++ Code, - FunctionOptions = [nounwind, noredzone, list_to_atom("gc \"erlang\"")], + FunctionOptions = [nounwind, noredzone, 'gc "erlang"'], WordTy = hipe_llvm:mk_int(?BITS_IN_WORD), FunRetTy = hipe_llvm:mk_struct(lists:duplicate(?NR_PINNED_REGS + 1, WordTy)), hipe_llvm:mk_fun_def([], [], "cc 11", [], FunRetTy, FunctionName, Args, -- cgit v1.2.3 From 61027e62a901ec12cc27d3b08ad80dd47ccf2a3f Mon Sep 17 00:00:00 2001 From: Kostis Sagonas Date: Thu, 23 Mar 2017 09:57:45 +0100 Subject: Remove (now) unnecessary argument of pack_constants --- lib/hipe/llvm/hipe_llvm_merge.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/hipe/llvm') diff --git a/lib/hipe/llvm/hipe_llvm_merge.erl b/lib/hipe/llvm/hipe_llvm_merge.erl index 6e891ac3b0..58d862fbb2 100644 --- a/lib/hipe/llvm/hipe_llvm_merge.erl +++ b/lib/hipe/llvm/hipe_llvm_merge.erl @@ -13,7 +13,7 @@ finalize(CompiledCode, Closures, Exports) -> Code = [{MFA, [], ConstTab} || {MFA, _, _ , ConstTab, _, _} <- CompiledCode1], {ConstAlign, ConstSize, ConstMap, RefsFromConsts} = - hipe_pack_constants:pack_constants(Code, ?ARCH_REGISTERS:alignment()), + hipe_pack_constants:pack_constants(Code), %% Compute total code size separately as a sanity check for alignment CodeSize = compute_code_size(CompiledCode1, 0), %% io:format("Code Size (pre-computed): ~w~n", [CodeSize]), -- cgit v1.2.3 From d9a6b8d2f761f6c16fd0772b65a3c4b6169f3b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20L=C3=A5ng?= Date: Thu, 30 Mar 2017 12:01:53 +0200 Subject: Fix ErLLVM in --enable-m32-build builds By having ErLLVM explicitly tell LLVM which architecture we're expecting it to compile for we remove the risk of having LLVM generate amd64 code for a x86 VM. --- lib/hipe/llvm/Makefile | 3 +-- lib/hipe/llvm/hipe_llvm_main.erl | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) (limited to 'lib/hipe/llvm') diff --git a/lib/hipe/llvm/Makefile b/lib/hipe/llvm/Makefile index 88016a7d8b..e8d9a0e8bb 100644 --- a/lib/hipe/llvm/Makefile +++ b/lib/hipe/llvm/Makefile @@ -73,8 +73,7 @@ include ../native.mk ERL_COMPILE_FLAGS += -Werror +inline +warn_export_vars #+warn_missing_spec # if in 32 bit backend define BIT32 symbol -ARCH = $(shell echo $(TARGET) | sed 's/^\(x86_64\)-.*/64bit/') -ifneq ($(ARCH), 64bit) +ifneq ($(BITS64),yes) ERL_COMPILE_FLAGS += -DBIT32 endif diff --git a/lib/hipe/llvm/hipe_llvm_main.erl b/lib/hipe/llvm/hipe_llvm_main.erl index 0957dd4df2..4eec0c752b 100644 --- a/lib/hipe/llvm/hipe_llvm_main.erl +++ b/lib/hipe/llvm/hipe_llvm_main.erl @@ -108,8 +108,10 @@ llvm_llc(Dir, Filename, Ver, Options) -> OptLevel = trans_optlev_flag(llc, Options), VerFlags = llc_ver_flags(Ver), Align = find_stack_alignment(), + Target = llc_target_opt(), LlcFlags = [OptLevel, "-code-model=medium", "-stack-alignment=" ++ Align , "-tailcallopt", "-filetype=asm" %FIXME + , Target | VerFlags], Command = "llc " ++ fix_opts(LlcFlags) ++ " " ++ Source, %% io:format("LLC: ~s~n", [Command]), @@ -123,7 +125,8 @@ llvm_llc(Dir, Filename, Ver, Options) -> compile(Dir, Fun_Name, Compiler) -> Source = Dir ++ Fun_Name ++ ".s", Dest = Dir ++ Fun_Name ++ ".o", - Command = Compiler ++ " -c " ++ Source ++ " -o " ++ Dest, + Target = compiler_target_opt(), + Command = Compiler ++ " " ++ Target ++ " -c " ++ Source ++ " -o " ++ Dest, %% io:format("~s: ~s~n", [Compiler, Command]), case os:cmd(Command) of "" -> ok; @@ -137,6 +140,18 @@ find_stack_alignment() -> _ -> exit({?MODULE, find_stack_alignment, "Unimplemented architecture"}) end. +llc_target_opt() -> + case get(hipe_target_arch) of + x86 -> "-march=x86"; + amd64 -> "-march=x86-64" + end. + +compiler_target_opt() -> + case get(hipe_target_arch) of + x86 -> "-m32"; + amd64 -> "-m64" + end. + %% @doc Join options. fix_opts(Opts) -> string:join(Opts, " "). -- cgit v1.2.3 From 83e20c62057ebc1d8064bf57b01be560cd244e1d Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Thu, 4 May 2017 15:42:21 +0200 Subject: Update copyright year --- lib/hipe/llvm/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/hipe/llvm') diff --git a/lib/hipe/llvm/Makefile b/lib/hipe/llvm/Makefile index e8d9a0e8bb..817ff67dcd 100644 --- a/lib/hipe/llvm/Makefile +++ b/lib/hipe/llvm/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2001-2016. All Rights Reserved. +# Copyright Ericsson AB 2001-2017. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. -- cgit v1.2.3