Don't use emit_parts_list for regular operations.

Using emit_parts_list does not make sense for any
operation except Ialloc, where we can delay the
computation of simple expression until the allocation
is done. So we try to avoid using emit_parts_list for
regular operations, where the special treatment of
non simple expression conflicts with our special
instruction selection on arm (and arm64). For example
we cannot merge the add and shift operation required
for tagging as soon as there is at least one non
simple expression involved, even though both Cadd
and Clsl do not care at all whether its arguments are
simple or not.

git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@14292 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
master
Benedikt Meurer 2013-11-14 08:10:03 +00:00
parent 4818fbba05
commit 7fab955f7b
1 changed files with 69 additions and 54 deletions

View File

@ -436,11 +436,7 @@ method emit_expr env exp =
| Ctuple [] ->
Some [||]
| Ctuple exp_list ->
begin match self#emit_parts_list env exp_list with
None -> None
| Some(simple_list, ext_env) ->
Some(self#emit_tuple ext_env simple_list)
end
self#emit_expr_list env exp_list
| Cop(Craise (k, dbg), [arg]) ->
begin match self#emit_expr env arg with
None -> None
@ -453,55 +449,59 @@ method emit_expr env exp =
| Cop(Ccmpf comp, args) ->
self#emit_expr env (Cifthenelse(exp, Cconst_int 1, Cconst_int 0))
| Cop(op, args) ->
begin match self#emit_parts_list env args with
None -> None
| Some(simple_args, env) ->
let ty = oper_result_type op in
let (new_op, new_args) = self#select_operation op simple_args in
let dbg = debuginfo_op op in
match new_op with
Icall_ind ->
let ty = oper_result_type op in
let (new_op, new_args) = self#select_operation op args in
let dbg = debuginfo_op op in
begin match new_op with
Icall_ind | Icall_imm _ | Iextcall _ | Ialloc _ ->
begin match self#emit_parts_list env new_args with
None -> None
| Some(new_args, env) ->
Proc.contains_calls := true;
let r1 = self#emit_tuple env new_args in
let rarg = Array.sub r1 1 (Array.length r1 - 1) in
let rd = self#regs_for ty in
let (loc_arg, stack_ofs) = Proc.loc_arguments rarg in
let loc_res = Proc.loc_results rd in
self#insert_move_args rarg loc_arg stack_ofs;
self#insert_debug (Iop Icall_ind) dbg
(Array.append [|r1.(0)|] loc_arg) loc_res;
self#insert_move_results loc_res rd stack_ofs;
Some rd
| Icall_imm lbl ->
Proc.contains_calls := true;
let r1 = self#emit_tuple env new_args in
let rd = self#regs_for ty in
let (loc_arg, stack_ofs) = Proc.loc_arguments r1 in
let loc_res = Proc.loc_results rd in
self#insert_move_args r1 loc_arg stack_ofs;
self#insert_debug (Iop(Icall_imm lbl)) dbg loc_arg loc_res;
self#insert_move_results loc_res rd stack_ofs;
Some rd
| Iextcall(lbl, alloc) ->
Proc.contains_calls := true;
let (loc_arg, stack_ofs) =
self#emit_extcall_args env new_args in
let rd = self#regs_for ty in
let loc_res = self#insert_op_debug (Iextcall(lbl, alloc)) dbg
loc_arg (Proc.loc_external_results rd) in
self#insert_move_results loc_res rd stack_ofs;
Some rd
| Ialloc _ ->
Proc.contains_calls := true;
let rd = self#regs_for typ_addr in
let size = size_expr env (Ctuple new_args) in
self#insert (Iop(Ialloc size)) [||] rd;
self#emit_stores env new_args rd;
Some rd
| op ->
let r1 = self#emit_tuple env new_args in
match new_op with
Icall_ind ->
let r1 = self#emit_tuple env new_args in
let rarg = Array.sub r1 1 (Array.length r1 - 1) in
let rd = self#regs_for ty in
let (loc_arg, stack_ofs) = Proc.loc_arguments rarg in
let loc_res = Proc.loc_results rd in
self#insert_move_args rarg loc_arg stack_ofs;
self#insert_debug (Iop new_op) dbg
(Array.append [|r1.(0)|] loc_arg) loc_res;
self#insert_move_results loc_res rd stack_ofs;
Some rd
| Icall_imm _ ->
let r1 = self#emit_tuple env new_args in
let rd = self#regs_for ty in
let (loc_arg, stack_ofs) = Proc.loc_arguments r1 in
let loc_res = Proc.loc_results rd in
self#insert_move_args r1 loc_arg stack_ofs;
self#insert_debug (Iop new_op) dbg loc_arg loc_res;
self#insert_move_results loc_res rd stack_ofs;
Some rd
| Iextcall _ ->
let (loc_arg, stack_ofs) =
self#emit_extcall_args env new_args in
let rd = self#regs_for ty in
let loc_res = self#insert_op_debug new_op dbg
loc_arg (Proc.loc_external_results rd) in
self#insert_move_results loc_res rd stack_ofs;
Some rd
| Ialloc _ ->
let rd = self#regs_for typ_addr in
let size = size_expr env (Ctuple new_args) in
self#insert_debug (Iop(Ialloc size)) dbg [||] rd;
self#emit_stores env new_args rd;
Some rd
| _ -> assert false
end
| op ->
begin match self#emit_expr_list env new_args with
None -> None
| Some r1 ->
let rd = self#regs_for ty in
Some (self#insert_op_debug op dbg r1 rd)
end
end
| Csequence(e1, e2) ->
begin match self#emit_expr env e1 with
@ -553,10 +553,9 @@ method emit_expr env exp =
self#insert (Icatch(nfail, s1#extract, s2#extract)) [||] [||];
r
| Cexit (nfail,args) ->
begin match self#emit_parts_list env args with
begin match self#emit_expr_list env args with
None -> None
| Some (simple_list, ext_env) ->
let src = self#emit_tuple ext_env simple_list in
| Some src ->
let dest =
try List.assoc nfail !catch_regs
with Not_found ->
@ -632,6 +631,22 @@ method private emit_parts_list env exp_list =
None -> None
| Some(new_exp, fin_env) -> Some(new_exp :: new_rem, fin_env)
method private emit_expr_list env exp_list =
let rec emit_list = function
[] -> Some([])
| exp :: rem ->
(* This ensures right-to-left evaluation, consistent with the
bytecode compiler *)
match emit_list rem with
None -> None
| Some(loc_rem) ->
match self#emit_expr env exp with
None -> None
| Some(loc_exp) -> Some(loc_exp :: loc_rem) in
match emit_list exp_list with
None -> None
| Some(loc_list) -> Some(Array.concat loc_list)
method private emit_tuple env exp_list =
let rec emit_list = function
[] -> []