summaryrefslogtreecommitdiff
path: root/asmcomp/i386
diff options
context:
space:
mode:
authorDamien Doligez <damien.doligez-inria.fr>2014-04-28 11:49:52 +0000
committerDamien Doligez <damien.doligez-inria.fr>2014-04-28 11:49:52 +0000
commitcc25e53ad310eb32d4854a1505ac3a9a917c8368 (patch)
tree101a8f24490f8ef63c75820cfd945cc4d7f669fc /asmcomp/i386
parente94190206fe983154d5606a448e434aec03783d0 (diff)
parentf1f362698f931494a305d48667936ffee2012b64 (diff)
downloadocaml-safe-string.tar.gz
merge trunk up to commit 14699safe-string
git-svn-id: http://caml.inria.fr/svn/ocaml/branches/safe-string@14700 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
Diffstat (limited to 'asmcomp/i386')
-rw-r--r--asmcomp/i386/CSE.ml48
-rw-r--r--asmcomp/i386/arch.ml17
-rw-r--r--asmcomp/i386/emit.mlp23
-rw-r--r--asmcomp/i386/emit_nt.mlp45
-rw-r--r--asmcomp/i386/proc.ml14
-rw-r--r--asmcomp/i386/selection.ml16
6 files changed, 108 insertions, 55 deletions
diff --git a/asmcomp/i386/CSE.ml b/asmcomp/i386/CSE.ml
new file mode 100644
index 0000000000..3ce4567024
--- /dev/null
+++ b/asmcomp/i386/CSE.ml
@@ -0,0 +1,48 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2014 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* CSE for the i386 *)
+
+open Cmm
+open Arch
+open Mach
+open CSEgen
+
+class cse = object (self)
+
+inherit cse_generic as super
+
+method! class_of_operation op =
+ match op with
+ (* Operations that affect the floating-point stack cannot be factored *)
+ | Iconst_float _ | Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf
+ | Iintoffloat | Ifloatofint
+ | Iload((Single | Double | Double_u), _) -> Op_other
+ (* Specific ops *)
+ | Ispecific(Ilea _) -> Op_pure
+ | Ispecific(Istore_int(_, _, is_asg)) -> Op_store is_asg
+ | Ispecific(Istore_symbol(_, _, is_asg)) -> Op_store is_asg
+ | Ispecific(Ioffset_loc(_, _)) -> Op_store true
+ | Ispecific _ -> Op_other
+ | _ -> super#class_of_operation op
+
+method! is_cheap_operation op =
+ match op with
+ | Iconst_int _ | Iconst_blockheader _ -> true
+ | Iconst_symbol _ -> true
+ | _ -> false
+
+end
+
+let fundecl f =
+ (new cse)#fundecl f
+
diff --git a/asmcomp/i386/arch.ml b/asmcomp/i386/arch.ml
index d2f9fd61a8..0d2130445e 100644
--- a/asmcomp/i386/arch.ml
+++ b/asmcomp/i386/arch.ml
@@ -31,8 +31,8 @@ type addressing_mode =
type specific_operation =
Ilea of addressing_mode (* Lea gives scaled adds *)
- | Istore_int of nativeint * addressing_mode (* Store an integer constant *)
- | Istore_symbol of string * addressing_mode (* Store a symbol *)
+ | Istore_int of nativeint * addressing_mode * bool (* Store an integer constant *)
+ | Istore_symbol of string * addressing_mode * bool (* Store a symbol *)
| Ioffset_loc of int * addressing_mode (* Add a constant to a location *)
| Ipush (* Push regs on stack *)
| Ipush_int of nativeint (* Push an integer constant *)
@@ -105,11 +105,14 @@ let print_addressing printreg addr ppf arg =
let print_specific_operation printreg op ppf arg =
match op with
| Ilea addr -> print_addressing printreg addr ppf arg
- | Istore_int(n, addr) ->
- fprintf ppf "[%a] := %s" (print_addressing printreg addr) arg
- (Nativeint.to_string n)
- | Istore_symbol(lbl, addr) ->
- fprintf ppf "[%a] := \"%s\"" (print_addressing printreg addr) arg lbl
+ | Istore_int(n, addr, is_assign) ->
+ fprintf ppf "[%a] := %nd %s"
+ (print_addressing printreg addr) arg n
+ (if is_assign then "(assign)" else "(init)")
+ | Istore_symbol(lbl, addr, is_assign) ->
+ fprintf ppf "[%a] := \"%s\" %s"
+ (print_addressing printreg addr) arg lbl
+ (if is_assign then "(assign)" else "(init)")
| Ioffset_loc(n, addr) ->
fprintf ppf "[%a] +:= %i" (print_addressing printreg addr) arg n
| Ipush ->
diff --git a/asmcomp/i386/emit.mlp b/asmcomp/i386/emit.mlp
index 2b90d37f64..98df5f958b 100644
--- a/asmcomp/i386/emit.mlp
+++ b/asmcomp/i386/emit.mlp
@@ -412,15 +412,16 @@ let emit_floatspecial = function
(* Floating-point constants *)
-let float_constants = ref ([] : (string * int) list)
+let float_constants = ref ([] : (int64 * int) list)
let add_float_constant cst =
+ let repr = Int64.bits_of_float cst in
try
- List.assoc cst !float_constants
+ List.assoc repr !float_constants
with
Not_found ->
let lbl = new_label() in
- float_constants := (cst, lbl) :: !float_constants;
+ float_constants := (repr, lbl) :: !float_constants;
lbl
let emit_float_constant (cst, lbl) =
@@ -465,8 +466,8 @@ let emit_instr fallthrough i =
| _ -> ` movl $0, {emit_reg i.res.(0)}\n`
end else
` movl ${emit_nativeint n}, {emit_reg i.res.(0)}\n`
- | Lop(Iconst_float s) ->
- begin match Int64.bits_of_float (float_of_string s) with
+ | Lop(Iconst_float f) ->
+ begin match Int64.bits_of_float f with
| 0x0000_0000_0000_0000L -> (* +0.0 *)
` fldz\n`
| 0x8000_0000_0000_0000L -> (* -0.0 *)
@@ -476,7 +477,7 @@ let emit_instr fallthrough i =
| 0xBFF0_0000_0000_0000L -> (* -1.0 *)
` fld1\n fchs\n`
| _ ->
- let lbl = add_float_constant s in
+ let lbl = add_float_constant f in
` fldl {emit_label lbl}\n`
end
| Lop(Iconst_symbol s) ->
@@ -543,7 +544,7 @@ let emit_instr fallthrough i =
| Double | Double_u ->
` fldl {emit_addressing addr i.arg 0}\n`
end
- | Lop(Istore(chunk, addr)) ->
+ | Lop(Istore(chunk, addr, _)) ->
begin match chunk with
| Word | Thirtytwo_signed | Thirtytwo_unsigned ->
` movl {emit_reg i.arg.(0)}, {emit_addressing addr i.arg 1}\n`
@@ -683,9 +684,9 @@ let emit_instr fallthrough i =
stack_offset := !stack_offset + 8
| Lop(Ispecific(Ilea addr)) ->
` lea {emit_addressing addr i.arg 0}, {emit_reg i.res.(0)}\n`
- | Lop(Ispecific(Istore_int(n, addr))) ->
+ | Lop(Ispecific(Istore_int(n, addr, _))) ->
` movl ${emit_nativeint n}, {emit_addressing addr i.arg 0}\n`
- | Lop(Ispecific(Istore_symbol(s, addr))) ->
+ | Lop(Ispecific(Istore_symbol(s, addr, _))) ->
` movl ${emit_symbol s}, {emit_addressing addr i.arg 0}\n`
| Lop(Ispecific(Ioffset_loc(n, addr))) ->
` addl ${emit_int n}, {emit_addressing addr i.arg 0}\n`
@@ -960,9 +961,9 @@ let emit_item = function
| Cint n ->
` .long {emit_nativeint n}\n`
| Csingle f ->
- emit_float32_directive ".long" f
+ emit_float32_directive ".long" (Int32.bits_of_float f)
| Cdouble f ->
- emit_float64_split_directive ".long" f
+ emit_float64_split_directive ".long" (Int64.bits_of_float f)
| Csymbol_address s ->
` .long {emit_symbol s}\n`
| Clabel_address lbl ->
diff --git a/asmcomp/i386/emit_nt.mlp b/asmcomp/i386/emit_nt.mlp
index 495a29aecc..a9c9db3e4f 100644
--- a/asmcomp/i386/emit_nt.mlp
+++ b/asmcomp/i386/emit_nt.mlp
@@ -62,7 +62,10 @@ let add_used_symbol s =
let emit_symbol s =
emit_string "_"; Emitaux.emit_symbol '$' s
+(* Output a 32 or 64 bit integer in hex *)
+
let emit_int32 n = emit_printf "0%lxh" n
+let emit_int64 n = emit_printf "0%Lxh" n
(* Output a label *)
@@ -361,36 +364,20 @@ let emit_floatspecial = function
(* Floating-point constants *)
-let float_constants = ref ([] : (string * int) list)
+let float_constants = ref ([] : (int64 * int) list)
let add_float_constant cst =
+ let repr = Int64.bits_of_float cst in
try
- List.assoc cst !float_constants
+ List.assoc repr !float_constants
with
Not_found ->
let lbl = new_label() in
- float_constants := (cst, lbl) :: !float_constants;
+ float_constants := (repr, lbl) :: !float_constants;
lbl
-let emit_float s =
- (* MASM doesn't like floating-point constants such as 2e9.
- Turn them into 2.0e9. *)
- let pos_e = ref (-1) and pos_dot = ref (-1) in
- for i = 0 to String.length s - 1 do
- match s.[i] with
- 'e'|'E' -> pos_e := i
- | '.' -> pos_dot := i
- | _ -> ()
- done;
- if !pos_dot < 0 && !pos_e >= 0 then begin
- emit_string (String.sub s 0 !pos_e);
- emit_string ".0";
- emit_string (String.sub s !pos_e (String.length s - !pos_e))
- end else
- emit_string s
-
let emit_float_constant (cst, lbl) =
- `{emit_label lbl} REAL8 {emit_float cst}\n`
+ `{emit_label lbl}: QWORD {emit_int64 cst}\n`
(* Output the assembly code for an instruction *)
@@ -426,8 +413,8 @@ let emit_instr i =
| _ -> ` mov {emit_reg i.res.(0)}, 0\n`
end else
` mov {emit_reg i.res.(0)}, {emit_nativeint n}\n`
- | Lop(Iconst_float s) ->
- begin match Int64.bits_of_float (float_of_string s) with
+ | Lop(Iconst_float f) ->
+ begin match Int64.bits_of_float f with
| 0x0000_0000_0000_0000L -> (* +0.0 *)
` fldz\n`
| 0x8000_0000_0000_0000L -> (* -0.0 *)
@@ -437,7 +424,7 @@ let emit_instr i =
| 0xBFF0_0000_0000_0000L -> (* -1.0 *)
` fld1\n fchs\n`
| _ ->
- let lbl = add_float_constant s in
+ let lbl = add_float_constant f in
` fld {emit_label lbl}\n`
end
| Lop(Iconst_symbol s) ->
@@ -493,7 +480,7 @@ let emit_instr i =
| Double | Double_u ->
` fld REAL8 PTR {emit_addressing addr i.arg 0}\n`
end
- | Lop(Istore(chunk, addr)) ->
+ | Lop(Istore(chunk, addr, _)) ->
begin match chunk with
| Word | Thirtytwo_signed | Thirtytwo_unsigned ->
` mov DWORD PTR {emit_addressing addr i.arg 1}, {emit_reg i.arg.(0)}\n`
@@ -631,9 +618,9 @@ let emit_instr i =
stack_offset := !stack_offset + 8
| Lop(Ispecific(Ilea addr)) ->
` lea {emit_reg i.res.(0)}, DWORD PTR {emit_addressing addr i.arg 0}\n`
- | Lop(Ispecific(Istore_int(n, addr))) ->
+ | Lop(Ispecific(Istore_int(n, addr, _))) ->
` mov DWORD PTR {emit_addressing addr i.arg 0},{emit_nativeint n}\n`
- | Lop(Ispecific(Istore_symbol(s, addr))) ->
+ | Lop(Ispecific(Istore_symbol(s, addr, _))) ->
add_used_symbol s ;
` mov DWORD PTR {emit_addressing addr i.arg 0},OFFSET {emit_symbol s}\n`
| Lop(Ispecific(Ioffset_loc(n, addr))) ->
@@ -816,9 +803,9 @@ let emit_item = function
| Cint32 n ->
` DWORD {emit_nativeint n}\n`
| Csingle f ->
- ` REAL4 {emit_float f}\n`
+ ` DWORD {emit_int32 (Int32.bits_of_float f)}\n`
| Cdouble f ->
- ` REAL8 {emit_float f}\n`
+ ` QWORD {emit_int64 (Int64.bits_of_float f)}\n`
| Csymbol_address s ->
add_used_symbol s ;
` DWORD {emit_symbol s}\n`
diff --git a/asmcomp/i386/proc.ml b/asmcomp/i386/proc.ml
index d80d182088..38bfdb29f9 100644
--- a/asmcomp/i386/proc.ml
+++ b/asmcomp/i386/proc.ml
@@ -182,6 +182,20 @@ let max_register_pressure = function
Iintoffloat -> [| 6; max_int |]
| _ -> [|7; max_int |]
+(* Pure operations (without any side effect besides updating their result
+ registers). Note that floating-point operations are not pure
+ because they update the float stack. *)
+
+let op_is_pure = function
+ | Icall_ind | Icall_imm _ | Itailcall_ind | Itailcall_imm _
+ | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _
+ | Iintop(Icheckbound) | Iintop_imm(Icheckbound, _) -> false
+ | Iconst_float _ | Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf
+ | Iintoffloat | Ifloatofint | Iload((Single | Double | Double_u), _) -> false
+ | Ispecific(Ilea _) -> true
+ | Ispecific _ -> false
+ | _ -> true
+
(* Layout of the stack frame *)
let num_stack_slots = [| 0; 0 |]
diff --git a/asmcomp/i386/selection.ml b/asmcomp/i386/selection.ml
index d86f1b2823..10d2d40e37 100644
--- a/asmcomp/i386/selection.ml
+++ b/asmcomp/i386/selection.ml
@@ -135,7 +135,7 @@ let pseudoregs_for_operation op arg res =
(* For storing a byte, the argument must be in eax...edx.
(But for a short, any reg will do!)
Keep it simple, just force the argument to be in edx. *)
- | Istore((Byte_unsigned | Byte_signed), addr) ->
+ | Istore((Byte_unsigned | Byte_signed), addr, _) ->
let newarg = Array.copy arg in
newarg.(0) <- edx;
(newarg, res, false)
@@ -178,20 +178,20 @@ method select_addressing chunk exp =
| (Ascaledadd(e1, e2, scale), d) ->
(Iindexed2scaled(scale, d), Ctuple[e1; e2])
-method! select_store addr exp =
+method! select_store is_assign addr exp =
match exp with
Cconst_int n ->
- (Ispecific(Istore_int(Nativeint.of_int n, addr)), Ctuple [])
+ (Ispecific(Istore_int(Nativeint.of_int n, addr, is_assign)), Ctuple [])
| (Cconst_natint n | Cconst_blockheader n) ->
- (Ispecific(Istore_int(n, addr)), Ctuple [])
+ (Ispecific(Istore_int(n, addr, is_assign)), Ctuple [])
| Cconst_pointer n ->
- (Ispecific(Istore_int(Nativeint.of_int n, addr)), Ctuple [])
+ (Ispecific(Istore_int(Nativeint.of_int n, addr, is_assign)), Ctuple [])
| Cconst_natpointer n ->
- (Ispecific(Istore_int(n, addr)), Ctuple [])
+ (Ispecific(Istore_int(n, addr, is_assign)), Ctuple [])
| Cconst_symbol s ->
- (Ispecific(Istore_symbol(s, addr)), Ctuple [])
+ (Ispecific(Istore_symbol(s, addr, is_assign)), Ctuple [])
| _ ->
- super#select_store addr exp
+ super#select_store is_assign addr exp
method! select_operation op args =
match op with