-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCodeElimination.ml
147 lines (125 loc) · 4.09 KB
/
CodeElimination.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
open OptimizationSupport
open QuadTypes
open Error
open Symbol
open Identifier
open Debug
open Types
(* Unreachable code Elimination *)
(* First iterate through all blocks and delete everything after
* an unconditional jump or a ret - useful particularly before
* converting to a flowgraph - issue a warning *)
let delete_after_jumps block =
let n = Array.length block in
let rec loop i =
if i < n then
begin
match block.(i) with
| Quad_ret
| Quad_jump _ ->
loop_delete (i+1)
| _ -> loop (i+1)
end
and loop_delete i =
if i < n then
begin
block.(i) <- Quad_dummy;
loop_delete (i+1)
end in
loop 0
(* Perform the above deletions in basic blocks *)
let perform_deletions quads =
Array.iter (Array.iter delete_after_jumps) quads
(* DFS in a flowgraph to determine unreachable from entry *)
let find_unreachable flowgraph =
let n = Array.length flowgraph in
let visited = Array.make n false in
let rec dfs i =
visited.(i) <- true;
List.iter (fun x -> if (not visited.(x)) then dfs x) flowgraph.(i).children in
dfs 0;
for i = 0 to n-1 do
if (not visited.(i))
then (
flowgraph.(i) <- {flowgraph.(i) with code_block = Array.make 0 Quad_dummy};
)
done
(* Use the above to do it in all Flowgraphs *)
let delete_unreachable_blocks flowgraphs =
Array.iter find_unreachable flowgraphs
(* Eliminate extraneous temporary variables *)
let single_delete_temporary_variables fun_code =
let temps = ref EntrySet.empty in
let handle_single_block block =
let handle_use q =
match q with
| Quad_valof ent -> temps := EntrySet.add ent !temps
| Quad_entry ent -> (
match ent.entry_info with
| ENTRY_temporary _ -> temps := EntrySet.add ent !temps
| _ -> ()
)
| _ -> () in
let handle_single_quad = function
| Quad_calc (_, q1, q2, q3) ->
handle_use q1;
handle_use q2;
handle_use q3
| Quad_cond (_, q1, q2, _) ->
handle_use q1;
handle_use q2
| Quad_set (q1, q2) ->
handle_use q1;
handle_use q2
| Quad_array (_, q, e) ->
handle_use q;
temps := EntrySet.add e !temps
| Quad_par (q, _) ->
handle_use q
| _ -> () in
Array.iter handle_single_quad block in
Array.iter handle_single_block fun_code;
if !debug_temporary_deletion then begin
Printf.printf "Temporaries used:\n";
EntrySet.iter (fun e -> Printf.printf "<%s> " (id_name e.entry_id)) !temps;
Printf.printf "\n";
end;
(* Extract the function entry *)
let f =
match fun_code.(0).(0) with
| Quad_unit f -> f
| _ -> internal "First quad not a unit"; raise Terminate in
(* Extract the scope from the function *)
let scope =
match f.entry_info with
| ENTRY_function fun_info -> (
match fun_info.function_scope with
| Some scope -> scope
| None -> internal "No scope registered"; raise Terminate
)
| _ -> internal "Function not a function"; raise Terminate in
(* Find the last offset of the "local" information *)
let (acc, lst) = find_first_temporary_offset scope in
let temporary_offset = ref acc in
let entry_list = ref lst in
(* Debug *)
if !debug_temporary_deletion then begin
Printf.printf "Negofs are: %d\n" scope.sco_negofs;
Printf.printf "Temporary offset is at %d\n" !temporary_offset;
end;
let handle_single_temp entry =
let info =
match entry.entry_info with
| ENTRY_temporary temp_info -> temp_info
| _ -> internal "Not temporary"; raise Terminate in
temporary_offset := !temporary_offset - (sizeOfType info.temporary_type);
info.temporary_offset <- !temporary_offset;
entry_list := entry :: !entry_list in
EntrySet.iter handle_single_temp !temps;
scope.sco_negofs <- !temporary_offset;
scope.sco_entries <- !entry_list;
if !debug_temporary_deletion then begin
Printf.printf "Finally negofs become: %d\n" !temporary_offset;
end
let delete_temporary_variables block_code =
Array.iter single_delete_temporary_variables block_code