Skip to content

Commit 7595aca

Browse files
committed
Kill the preallocator, install a sane replacement. Closes rust-lang#131. And probably a lot of others.
1 parent 22c0776 commit 7595aca

File tree

5 files changed

+123
-263
lines changed

5 files changed

+123
-263
lines changed

Diff for: src/boot/be/abi.ml

+1-2
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,13 @@ type abi =
107107
abi_word_bits: Il.bits;
108108
abi_word_ty: Common.ty_mach;
109109

110-
abi_is_2addr_machine: bool;
111110
abi_has_pcrel_data: bool;
112111
abi_has_pcrel_code: bool;
113112

114113
abi_n_hardregs: int;
115114
abi_str_of_hardreg: (int -> string);
116115

117-
abi_prealloc_quad: (Il.quad' -> Il.quad');
116+
abi_emit_target_specific: (Il.emitter -> Il.quad -> unit);
118117
abi_constrain_vregs: (Il.quad -> Bits.t array -> unit);
119118

120119
abi_emit_fn_prologue: (Il.emitter

Diff for: src/boot/be/il.ml

+21-212
Original file line numberDiff line numberDiff line change
@@ -692,8 +692,7 @@ let string_of_quad (f:hreg_formatter) (q:quad) : string =
692692
type emitter = { mutable emit_pc: int;
693693
mutable emit_next_vreg: int option;
694694
mutable emit_next_spill: int;
695-
emit_preallocator: (quad' -> quad');
696-
emit_is_2addr: bool;
695+
emit_target_specific: (emitter -> quad -> unit);
697696
mutable emit_quads: quads;
698697
emit_annotations: (int,string) Hashtbl.t;
699698
emit_size_cache: ((size,operand) Hashtbl.t) Stack.t;
@@ -712,17 +711,15 @@ let deadq = { quad_fixup = None;
712711

713712

714713
let new_emitter
715-
(preallocator:quad' -> quad')
716-
(is_2addr:bool)
714+
(emit_target_specific:emitter -> quad -> unit)
717715
(vregs_ok:bool)
718716
(node:node_id option)
719717
: emitter =
720718
{
721719
emit_pc = 0;
722720
emit_next_vreg = (if vregs_ok then Some 0 else None);
723721
emit_next_spill = 0;
724-
emit_preallocator = preallocator;
725-
emit_is_2addr = is_2addr;
722+
emit_target_specific = emit_target_specific;
726723
emit_quads = Array.create 4 badq;
727724
emit_annotations = Hashtbl.create 0;
728725
emit_size_cache = Stack.create ();
@@ -837,218 +834,30 @@ let append_quad
837834
e.emit_pc <- e.emit_pc + 1
838835
;;
839836

837+
let default_mov q' =
838+
match q' with
839+
Binary b ->
840+
begin
841+
match b.binary_op with
842+
IDIV | IMUL | IMOD -> IMOV
843+
| _ -> UMOV
844+
end
845+
| Unary u ->
846+
begin
847+
match u.unary_op with
848+
IMOV -> IMOV
849+
| _ -> UMOV
850+
end
851+
| _ -> UMOV
852+
;;
840853

841854
let emit_full
842855
(e:emitter)
843856
(fix:fixup option)
844857
(q':quad')
845858
: unit =
846-
let fixup = ref fix in
847-
let emit_quad_bottom q' =
848-
append_quad e { quad_body = q';
849-
quad_fixup = (!fixup) };
850-
fixup := None;
851-
in
852-
853-
let emit_quad (q':quad') : unit =
854-
(* re-decay any freshly generated mem-mem movs. *)
855-
match q' with
856-
Unary { unary_dst = Mem (dst_mem, ScalarTy src_st);
857-
unary_src = Cell (Mem (src_mem, ScalarTy dst_st));
858-
unary_op = op }
859-
when is_mov op ->
860-
let v = next_vreg_cell e dst_st in
861-
emit_quad_bottom
862-
(unary op v (Cell (Mem (src_mem, ScalarTy src_st))));
863-
emit_quad_bottom
864-
(unary op (Mem (dst_mem, ScalarTy dst_st)) (Cell v))
865-
| _ -> emit_quad_bottom q'
866-
in
867-
868-
let default_mov =
869-
match q' with
870-
Binary b ->
871-
begin
872-
match b.binary_op with
873-
IDIV | IMUL | IMOD -> IMOV
874-
| _ -> UMOV
875-
end
876-
| Unary u ->
877-
begin
878-
match u.unary_op with
879-
IMOV -> IMOV
880-
| _ -> UMOV
881-
end
882-
| _ -> UMOV
883-
in
884-
885-
let emit_mov (dst:cell) (src:operand) : unit =
886-
emit_quad (unary default_mov dst src)
887-
in
888-
889-
let mov_if_operands_differ
890-
(old_op:operand) (new_op:operand)
891-
: unit =
892-
if (new_op <> old_op)
893-
then
894-
match new_op with
895-
(Cell new_cell) ->
896-
emit_mov new_cell old_op
897-
| _ -> ()
898-
in
899-
900-
let mov_if_two_operands_differ
901-
(old_lhs_op:operand) (new_lhs_op:operand)
902-
(old_rhs_op:operand) (new_rhs_op:operand)
903-
: unit =
904-
(*
905-
* This is sufficiently obscure that it deserves an explanation.
906-
*
907-
* The main idea here is to do two "mov_if_operands_differ" calls,
908-
* such as one might have when setting up a binary quad.
909-
*
910-
* The problem comes when you happen to hit a case like X86 div,
911-
* which preallocates *both* operands. Preallocating both means we
912-
* have to potentially issue two movs into the preallocated regs,
913-
* and the second of those movs might be a problem. Specifically:
914-
* the second mov-to-prealloc might make be moving from a
915-
* register-indirect mem cell based on a vreg, and that vreg may
916-
* wind up being assigned to an hreg that we just loaded with the
917-
* first mov. In other words, the second mov may retask the
918-
* preallocated hreg we set up in the first mov.
919-
*
920-
* You laugh, but of course this actually happens.
921-
*
922-
* So here we do a conservative thing and check to see if either
923-
* operand is memory-indirect at all. If either is, then for either
924-
* of the 'old' operands we're *about* to mov into a prealloc reg,
925-
* we first bounce them off a spill slot. Spill slots, thankfully,
926-
* we can always count on being able to address irrespective of the
927-
* opinions of the RA, as they are all just fp-relative.
928-
*
929-
* A slightly more aggressive version of this would only bounce
930-
* cases that are not fp-relative already, though doing so would
931-
* require threading the notion of what fp *is* through to
932-
* here. Possibly tighten this up in the future (or just
933-
* ... destroy this backend ASAP).
934-
*
935-
*)
936-
let has_reg_indirect op =
937-
match op with
938-
Cell (Mem _) -> true
939-
| _ -> false
940-
in
941-
let either_old_op_has_reg_indirect =
942-
(has_reg_indirect old_lhs_op) || (has_reg_indirect old_rhs_op)
943-
in
944-
let old_lhs_op =
945-
if either_old_op_has_reg_indirect && (new_lhs_op <> old_lhs_op)
946-
then
947-
let tmp =
948-
Mem (next_spill_slot e
949-
(ScalarTy (operand_scalar_ty old_lhs_op)))
950-
in
951-
emit_mov tmp old_lhs_op;
952-
Cell tmp
953-
else
954-
old_lhs_op
955-
in
956-
let old_rhs_op =
957-
if either_old_op_has_reg_indirect && (new_rhs_op <> old_rhs_op)
958-
then
959-
let tmp =
960-
Mem (next_spill_slot e
961-
(ScalarTy (operand_scalar_ty old_rhs_op)))
962-
in
963-
emit_mov tmp old_rhs_op;
964-
Cell tmp
965-
else
966-
old_rhs_op
967-
in
968-
mov_if_operands_differ old_lhs_op new_lhs_op;
969-
mov_if_operands_differ old_rhs_op new_rhs_op;
970-
in
971-
972-
let mov_if_cells_differ (old_cell:cell) (new_cell:cell) : unit =
973-
if not (new_cell = old_cell)
974-
then
975-
emit_mov old_cell (Cell new_cell)
976-
in
977-
978-
let emit_decayed_quad q' =
979-
match (q', e.emit_preallocator q') with
980-
(Binary b, Binary b') ->
981-
begin
982-
mov_if_two_operands_differ
983-
b.binary_lhs b'.binary_lhs
984-
b.binary_rhs b'.binary_rhs;
985-
if e.emit_is_2addr &&
986-
(not (b'.binary_lhs = (Cell b'.binary_dst)))
987-
then
988-
begin
989-
emit_mov b'.binary_dst b'.binary_lhs;
990-
emit_quad (Binary { b' with
991-
binary_lhs = (Cell b'.binary_dst) })
992-
end
993-
else
994-
emit_quad (Binary b');
995-
mov_if_cells_differ b.binary_dst b'.binary_dst
996-
end
997-
998-
| (Unary u, Unary u') ->
999-
mov_if_operands_differ u.unary_src u'.unary_src;
1000-
(* Assume '2addr' means '1addr' for unary ops. *)
1001-
if e.emit_is_2addr &&
1002-
(u'.unary_op = NEG || u'.unary_op = NOT) &&
1003-
(not (u'.unary_src = (Cell u'.unary_dst)))
1004-
then
1005-
begin
1006-
emit_mov u'.unary_dst u'.unary_src;
1007-
emit_quad (Unary { u' with unary_src = (Cell u'.unary_dst) })
1008-
end
1009-
else
1010-
emit_quad (Unary u');
1011-
mov_if_cells_differ u.unary_dst u'.unary_dst
1012-
1013-
| (Cmp c, Cmp c') ->
1014-
mov_if_two_operands_differ
1015-
c.cmp_lhs c'.cmp_lhs
1016-
c.cmp_rhs c'.cmp_rhs;
1017-
emit_quad (Cmp c');
1018-
1019-
| (Push op, Push op') ->
1020-
mov_if_operands_differ op op';
1021-
emit_quad (Push op');
1022-
1023-
| (Pop c, Pop c') ->
1024-
emit_quad (Pop c');
1025-
mov_if_cells_differ c c'
1026-
1027-
| (Call c, Call c') ->
1028-
emit_quad (Call c');
1029-
mov_if_cells_differ c.call_dst c'.call_dst
1030-
1031-
| (Lea lea, Lea lea') ->
1032-
emit_quad (Lea lea');
1033-
mov_if_cells_differ lea.lea_dst lea'.lea_dst
1034-
1035-
| (x, y) ->
1036-
assert (x = y);
1037-
emit_quad x
1038-
in
1039-
1040-
(* pre-decay mem-mem movs. *)
1041-
match q' with
1042-
Unary { unary_dst = Mem (dst_mem, ScalarTy src_st);
1043-
unary_src = Cell (Mem (src_mem, ScalarTy dst_st));
1044-
unary_op = op }
1045-
when is_mov op ->
1046-
let v = next_vreg_cell e dst_st in
1047-
emit_decayed_quad
1048-
(unary op v (Cell (Mem (src_mem, ScalarTy src_st))));
1049-
emit_decayed_quad
1050-
(unary op (Mem (dst_mem, ScalarTy dst_st)) (Cell v))
1051-
| _ -> emit_decayed_quad q'
859+
e.emit_target_specific e { quad_body = q';
860+
quad_fixup = fix }
1052861
;;
1053862

1054863
let emit (e:emitter) (q':quad') : unit =

0 commit comments

Comments
 (0)