Follow-up to commit r14254: optimization of immediate division and modulus for ARM64. Completely untested.

git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@14257 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
master
Xavier Leroy 2013-11-01 18:10:18 +00:00
parent ec4b2fc9a6
commit bdb169a04f
2 changed files with 36 additions and 12 deletions

View File

@ -454,17 +454,41 @@ let emit_instr i =
| Lop(Iintop Imod) ->
` sdiv {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
` msub {emit_reg i.res.(0)}, {emit_reg reg_tmp1}, {emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}\n`
| Lop(Iintop_imm(Idiv, n)) -> (* n is a power of 2 *)
| Lop(Iintop_imm(Idiv, n)) ->
let l = Misc.log2 n in
` asr {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, #63\n`;
` add {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, {emit_reg reg_tmp1}, lsr {emit_int (64-l)}\n`;
` asr {emit_reg i.res.(0)}, {emit_reg reg_tmp1}, {emit_int l}\n`
| Lop(Iintop_imm(Imod, n)) -> (* n is a power of 2 *)
if n = 1 lsl l then begin
` asr {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, #63\n`;
` add {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, {emit_reg reg_tmp1}, lsr {emit_int (64-l)}\n`;
` asr {emit_reg i.res.(0)}, {emit_reg reg_tmp1}, {emit_int l}\n`
end else begin
let (m, p) = Selectgen.divimm_parameters (Nativeint.of_int n) in
emit_intconst reg_tmp1 m;
` smulh {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, {emit_reg reg_tmp1}\n`;
if m < 0n then
` add {emit_reg reg_tmp1}, {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}\n`;
if p > 0 then
` asr {emit_reg reg_tmp1}, #{emit_int p}\n`;
` add {emit_reg i.res.(0)}, {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, lsr 63\n`
end
| Lop(Iintop_imm(Imod, n)) ->
let l = Misc.log2 n in
` asr {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, #63\n`;
` add {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, {emit_reg reg_tmp1}, lsr {emit_int (64-l)}\n`;
` asr {emit_reg reg_tmp1}, {emit_reg reg_tmp1}, {emit_int l}\n`;
` sub {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg reg_tmp1}, lsl {emit_int l}\n`
if n = 1 lsl l then begin
` asr {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, #63\n`;
` add {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, {emit_reg reg_tmp1}, lsr {emit_int (64-l)}\n`;
` asr {emit_reg reg_tmp1}, {emit_reg reg_tmp1}, {emit_int l}\n`;
` sub {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg reg_tmp1}, lsl {emit_int l}\n`
end else begin
let (m, p) = Selectgen.divimm_parameters (Nativeint.of_int n) in
emit_intconst reg_tmp1 m;
` smulh {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, {emit_reg reg_tmp1}\n`;
if m < 0n then
` add {emit_reg reg_tmp1}, {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}\n`;
if p > 0 then
` asr {emit_reg reg_tmp1}, #{emit_int p}\n`;
` add {emit_reg reg_tmp1}, {emit_reg reg_tmp1}, {emit_reg i.arg.(0)}, lsr 63\n`;
emit_intconst reg_tmp2 (Nativeint.of_int n);
` msub {emit_reg i.res.(0)}, {emit_reg reg_tmp1}, {emit_reg reg_tmp2}, {emit_reg i.arg.(0)}\n`
end
| Lop(Iintop op) ->
let instr = name_for_int_operation op in
` {emit_string instr} {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`

View File

@ -194,17 +194,17 @@ method! select_operation op args =
(Iintop Imul, args)
end
(* Division and modulus *)
(* Recognize (x / cst) and (x % cst) only if cst is a power of 2. *)
(* Recognize (x / cst) and (x % cst) only if cst is > 0. *)
| Cdivi ->
begin match args with
| [arg; Cconst_int n] when n = 1 lsl Misc.log2 n ->
| [arg; Cconst_int n] when n > 0 ->
((if n = 1 then Imove else Iintop_imm(Idiv, n)), [arg])
| _ ->
(Iintop Idiv, args)
end
| Cmodi ->
begin match args with
| [arg; Cconst_int n] when n = 1 lsl Misc.log2 n ->
| [arg; Cconst_int n] when n > 0 ->
((if n = 1 then Iconst_int 0n else Iintop_imm(Imod, n)), [arg])
| _ ->
(Iintop Imod, args)